elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Rompecabezas de Bitcoin, Medio millón USD en premios


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Ejercicio básico de combinaciones
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 2 [3] 4 Ir Abajo Respuesta Imprimir
Autor Tema: Ejercicio básico de combinaciones  (Leído 31,389 veces)
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #20 en: 6 Mayo 2021, 01:02 am »

Hola.
Hoy he llegado tarde del trabajo, pero todavía he sacado un tiempito para calcular las cantidades...

Dado que (ahora) varía la cantidad de unidades y decenas que pueden aparecer, lo adecuado es categorizar, pués a unidades iguales las firmas son las mismas, resumiendo:

- Con 0 decenas y 6 unidades: No puede darse: ej: 5,6,7,8,9 ?
   Falta 1 dígito para poder formar 6 'apuestas'.

- Con 1 decenas y 5 unidades: Puede o no aceptarse (técnicamente no, pues estaríamos inventando un dígito 0): ej: 3;  5,6,7,8,9
 35, 36, 37, 38, 39, 03?
En cualquier caso si se aceptara, sería una sola combinación y por tanto puede 'calcularse' manualmente. Luego puede dejarse fera.

- Con 2 decenas y 4 unidades: Salen 210 firmas distintas (son las calculadas anteriormente).
XY-RSTU
-------------------
XY XR XS XT XU
YX YR YS YT YU
Ej: 0,1,___6,7,8,9
 10, 08, 09, 16, 17, 19

- Con 3 decenas y 3 unidades: Salen 5.005 firmas.
XYZ-RST
-------------------
XY XZ XR XS XT
YX YZ YR YS YT
ZX ZY ZR ZS ZT
Ej: 0,1,2,___ 7,8,9
   20, 17, 28, 09, 27, 12

- Con 4 decenas y 2 unidades: Salen 38760 143.080 firmas.
WXYZ-RS
-------------------
WX WY WZ WR WS
XW XY XZ XR XS
YW YX YZ YR YS
ZE ZX ZY ZR ZS
Ej: 0,1,2,3,___ 8,9
 38,39,13, 01,29, 12

- Con 5 decenas y 1 unidad: Salen 177100 402.895 firmas.
VWXYZ-R    
-------------------    
VW VX VY VZ VR
WV WX WY WZ WR
XV XW XY XZ XR
YV YW YX YZ YR
ZV ZW ZX ZY ZR

Ej: 0,1,2,3,4,___ 9
   20,31,49, 43, 40

En total se aproximan al 1/4 de millón suben por encima del medio millón (y solo son las firmas).

p.d.: Mañana que vengo con más tiempo veré si me da tiempo a hacerlo.
p.d.2: Actualizado los valores de las combinaciones (había un error).


« Última modificación: 7 Mayo 2021, 15:46 pm por Serapis » En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #21 en: 6 Mayo 2021, 22:52 pm »

Me ha dado tiempo a rehacer lo que habíamos hecho, el resto es más de lo mismo y mañana en otro ratito lo completo... Al lío...

Dado que ahora tendremos varias categorías, es más eficiente crear una interfaz e implementar una clase por cada categoría, que andar complicando algoritmos con condicionales.

El código que tenías del proyecto previo, guardalo o bórralo... los cambios manuales son demasiados y es preferible copiar y pegar.

Añade un interfaz al proyecto. Este es el código de la interfaz:
Código
  1. Public Interface ICombina
  2.  
  3.    ''' <summary>
  4.    ''' Cantidad de valores enumerados.
  5.    ''' </summary>
  6.    ReadOnly Property Cantidad As UInt32
  7.  
  8.    ''' <summary>
  9.    ''' Recrea el array de las combinaciones al inicio.
  10.    ''' </summary>  
  11.    Sub Enumerar()
  12.  
  13.    ''' <summary>
  14.    ''' Decodifica el valor enumerado en la posicion indicada, a 6 pares de valores numericos.
  15.    ''' </summary>
  16.    ''' <param name="Index">Indice de la enumeracion solicitado</param>
  17.    ''' <param name="Decenas">Array de los digitos que (ademas) pueden actuar como decenas</param>
  18.    ''' <param name="Unidades">Array de los digitos que solo pueden actuar como unidades</param>
  19.    ''' <returns>Devuelve la combinacion con las 6 apuestas separadas por ', '"</returns>
  20.    Function Tranformar(ByVal Index As Int32, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String
  21. End Interface
  22.  

Los comentarios los puedes borrar si lo prefieres...
NOTA: La interfaz debe llamarse como figura ahí... luego que esté todo el código, podrás cambiarlo si lo prefieres.

Añade un módulo de código si no tienes alguno. Algunas funciones y extensiones de métodos se han trasladado aquí. es código estático (independiente de cualquier instancia). Este es el código a añadir dentro del módulo:
Código
  1.    <Extension()>
  2.    Public Function EnRango(ByVal Valor As Byte, ByVal Minimo As Byte, ByVal Maximo As Byte) As Boolean
  3.        Return ((Valor >= Minimo) And (Valor <= Maximo))
  4.    End Function
  5.    <Extension()>
  6.    Public Function EnRango(ByVal Valor As Char, ByVal Minimo As Byte, ByVal Maximo As Byte, ByVal Tope As Byte) As Boolean
  7.        Dim asci As Byte = (Strings.Asc(Valor) - Tope)
  8.        Return ((asci >= Minimo) And (asci <= Maximo))
  9.    End Function
  10.  
  11.  
  12.    Public Function EnumeraComb(ByRef Inicio As String, ByRef Final As String, ByVal Cantidad As UInteger) As String()
  13.        Dim k As UInt32 = 0
  14.        Dim Combina As String = Inicio
  15.        Dim Maxchar As Byte = IndexLastChar(Inicio, Final) ' Final.Chars(Final.Length-1)
  16.        Dim Permutas(0 To Cantidad - 1) As String
  17.        Dim digitos(0 To 5) As Byte, n As Byte = 0
  18.  
  19.        For k = 0 To 5
  20.            digitos(k) = k
  21.        Next
  22.  
  23.        k = 0
  24.        Do
  25.            Permutas(k) = Combina
  26.            If (digitos(5) = Maxchar) Then
  27.                n = 4
  28.                Do While Combina.Chars(n) = Combina.Chars(n + 1).Previo   '    digitos(n) = digitos(n + 1) - 1
  29.                    n -= 1
  30.                Loop
  31.  
  32.                digitos(n) += 1
  33.                For n = n + 1 To 5
  34.                    digitos(n) = digitos(n - 1) + 1
  35.                Next
  36.  
  37.                Combina = "" ' 0
  38.                For n = 0 To 5
  39.                    Combina &= CharIndexAZ(digitos(n)) ' * (10 ^ (5 - n))
  40.                Next
  41.            Else
  42.                Combina = Combina.NextComb()
  43.                digitos(5) += 1
  44.            End If
  45.            k += 1
  46.        Loop While (Combina < Final)
  47.        Permutas(k) = Combina
  48.  
  49.        Return Permutas
  50.    End Function
  51.  
  52. #Region "Las siguiente funciones y extensiones son solo de ayuda para la función anterior (enumerar)."
  53.    <Extension()>
  54.    Private Function NextComb(ByRef Combina As String) As String
  55.        Dim Last As Byte = Asc(Combina.Chars(5))  ' ojo Estamos usando siempre longitudes de 6 caracteres.
  56.        Return Strings.Left(Combina, 5) & Strings.Chr(Last + 1)
  57.    End Function
  58.  
  59.    ''' <summary>
  60.    ''' Calcula el caracter previo en la secuencia ASCII.
  61.    ''' </summary>
  62.    ''' <param name="Ch">Caracter en el rango A-Z</param>
  63.    ''' <returns>Devuelve el carácter previo al dado (en la secuencia ASCII).</returns>
  64.    ''' <remarks></remarks>
  65.    <Extension()>
  66.    Private Function Previo(ByRef Ch As Char) As Char
  67.        Dim n As Byte = Strings.Asc(Ch) - 1
  68.        Return Strings.Chr(n)
  69.    End Function
  70.  
  71.    Private Function CharIndexAZ(ByRef Index As Byte) As Char
  72.        Return Strings.Chr(65 + Index)
  73.    End Function
  74.  
  75.    ' Devuelve la distancia entre el primer caracter de inicio y el último de 'final'
  76.    ' Ejemplo: "'A'BCDEF" "EFGHI'J'" = 10;  "'A'BCDEF" "MNOPQ'R'" = 17
  77.    Private Function IndexLastChar(ByRef Inicio As String, ByRef Final As String) As Byte
  78.        Dim F As Byte = Strings.Asc(Final.Chars(Final.Length - 1))
  79.        Dim I As Byte = Strings.Asc(Inicio.Chars(0))
  80.  
  81.        Return (F - I)
  82.    End Function
  83. #End Region
  84.  

Se ha añadido alguna función, la principal es 'enumerarCombinacion'.
Las extensiones de métodos, son métodos que simplemente cambia la forma en que se llaman.
Si tu creas por ejemplo una función Ordenar que ordena un array, lo llamarías así:
 
Código
  1. call Ordenar(elArray, parametro1, parametro2)
Mediante una extensión, resulta más cómodo, pués se recurre al intellisense, para que pueda invocarse así:
  
Código
  1. elArray.Odenar(parametro1, parametro2)
Con lo que parece un método nativo más del tipo de datos al que se extiende. Naturalmente la extensión solo es aplicable al proyecto actual.

Finalmente volvemos a la ventana principal... (se asume que ahora mismo está vacía).
Código
  1. Public Class Form1
  2.    Private perm24, perm33, perm42, perm51,perm60 As ICombina
  3.    Private Decenas() As Byte, Unidades() As Byte
  4.  
  5.    Public Sub New()
  6.        InitializeComponent()
  7.        ' Crear las instancias una única vez.
  8.        perm24 = New Permutas2_4
  9.        perm33 = New Permutas3_3
  10.        perm42 = New Permutas4_2
  11.        perm51 = New Permutas5_1
  12.        perm60 = New Permutas6_0
  13.    End Sub
  14.  
  15.  
  16.    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  17.        Dim Nums() As String, txt As String
  18.        Dim k As UInt16, n As Byte
  19.        Dim Permuta As ICombina
  20.  
  21.        txt = TextBox1.Text.Replace(" ", "")
  22.        Nums = txt.Split(",")
  23.        If (Nums.Length = 6) Then
  24.            Array.Sort(Nums)
  25.            Do While (Nums(n).Chars(0).EnRango(0, 4, 48) = True) And (n < 5)
  26.                n += 1
  27.            Loop
  28.  
  29.            If (n.EnRango(1, 5) = True) Then
  30.                ReDim Decenas(0 To n - 1)
  31.                ReDim Unidades(0 To 6 - n - 1)
  32.  
  33.                For k = 0 To n - 1
  34.                    Decenas(k) = System.Byte.Parse(Nums(k))
  35.                Next
  36.                For k = n To 5
  37.                    Unidades(k - n) = System.Byte.Parse(Nums(k))
  38.                Next
  39.  
  40.                Select Case n
  41.                    Case 2 : Permuta = perm24
  42.                    Case 3 : Permuta = perm33
  43.                    Case 4 : Permuta = perm42
  44.                    Case 5 : Permuta = perm51
  45.                    case  6: Permuta = perm60
  46.                End Select
  47.  
  48.                ListBox1.Items.Clear()
  49.                For j = 0 To Permuta.Cantidad - 1
  50.                    ListBox1.Items.Add(Permuta.Tranformar(j, Decenas, Unidades))
  51.                Next
  52.                Label3.Text = "Cantidad en lista: " & Permuta.Cantidad.ToString ' ListBox1.Items.Count.ToString
  53.            Else
  54.                MessageBox.Show("No se puede generar combinaciones si no hay 2-5 dígitos menores de 5.")
  55.            End If
  56.        Else
  57.            MessageBox.Show("No, no no... Debe haber 6 y solo 6 numeros, separados por 1 coma...")
  58.        End If
  59.    End Sub
  60. End Class
  61.  

Se han sacado las clases fuera de la clase del formulario, por claridad.
Ahora hay una instancia de la interfaz 'ICombina', por cada categoría...
Se considera una categoría, a cada diferenciación en la relación de cantidad entre dígitos que pueden ser decenas de los que no.
Un ejemplo: Sean los dígitos 3, 6, 8, 0, 5, 1  ...hay 3 valores que pueden ser decenas: 0,1 y 3, luego pertenecen a la categoróa asociada a la intancia 'perm3_3 (3 decenas y 3 unidades, para qué complicarnos más en el nombre).
Esta diferenciaciónd e categorías es necesaria, porque cada una presenta diferente cantidad de firmas, como ya se señaló en el mensaje anterior.
en lo que al código de la función del botón respecta, para hallar a qué categoría pertenece, tras crear el array con los dígitos (nums), lo ordenamos, ahora un recorrido con un bucle nos permite contarlos, y luego selecciona la clase que operará conforme a la categoría reconocida.
Se descartan los casos en que haya 0 o 1 decena solo (5,5,6,7,8,9) y (2, 5,6,7,8,9) y también cuando sean 6 decenas (esto directamente lo he descartado, generaría varios millones de combinaciones)

En la misma ventana del formulario, bajo la clase de dicho formulario, irán la implementación de cada clase.
Como digo, de momento, solo he dejado lista, la conversión d ela primera (que es equivalente a la que ya hice), las otras son básicamente rehacer lo mismo con pequeños cambios en la función transformar, ya mañana en otro ratito, lo completo.
Código
  1.  
  2. Friend Class Permutas2_4
  3.    Implements ICombina
  4.  
  5.    Const MAX_COMBINAS As UInt16 = 210
  6.    Private s_Combinas() As String     ' UInt32
  7.  
  8.    Public Sub New()
  9.        Call Enumerar()
  10.    End Sub
  11.  
  12.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  13.        Get
  14.            Return MAX_COMBINAS
  15.        End Get
  16.    End Property
  17.  
  18.    ' Para generar las permutaciones, delega en la función que yace en el módulo.
  19.    Private Sub Enumerar() Implements ICombina.Enumerar
  20.        '             combinacion inicial, final, Total combinaciones
  21.        s_Combinas = EnumeraComb("ABCDEF", "EFGHIJ", MAX_COMBINAS)
  22.    End Sub
  23.  
  24.    ' Alfabeto = X,Y,   R,S,T,U
  25.    '  A   B   C   D   E      F   G   H   I   J
  26.    '  XY  XR  XS  XT  XU     YR  YS  YT  YU  YX            
  27.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  28.        Dim permuta As String = s_Combinas(Index)
  29.        Dim s(0 To 5) As String, valor As String = ""
  30.        Dim x As Byte = 0, k As Byte
  31.  
  32.        For k = 0 To 5
  33.            x = (Strings.Asc((permuta.Chars(k))) - 65)
  34.  
  35.            Select Case x
  36.                Case 0 : x = ((Decenas(0) * 10) + Decenas(1))
  37.                Case 1 To 4 : x = ((Decenas(0) * 10) + Unidades(x - 1))
  38.                Case 5 To 8 : x = ((Decenas(1) * 10) + Unidades(x - 5))
  39.                Case 9 : x = ((Decenas(1) * 10) + Decenas(0))
  40.            End Select
  41.  
  42.            If (x < 10) Then s(k) = "0" & x.ToString Else s(k) = x.ToString
  43.        Next
  44.  
  45.        Array.Sort(s)
  46.        Return Join(s, ", ")
  47.    End Function
  48. End Class
  49.  

Y eso es todo por hoy. Mañana lo completo.
Nota que ya se ha aprovechado para ordenar los elementos de cada combinación así además de estar el listado ordenado, también los valores de cada combinación.


p.d.: Corrijo, con 6 dígitos como decenas, se generan muchas menos firmas, cuando lo calculé ayer, creí haber leído millones... pués nada, mañana se incluye también y se hace el cambio pertienente para contener su clase y en la llamada del botón considerar el caso.

p.d.: Corregido cantidad de combinaciones para 4_2 y 5_1


« Última modificación: 10 Mayo 2021, 17:05 pm por Serapis » En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #22 en: 7 Mayo 2021, 15:40 pm »

Tengo un momento hoy tras comer, aprovecho para terminarlo...

Antes de nada, es conveniente aclarar que cometí un pequeño error (un '0' donde debí poner una 'O', que como es copia y pega... se tradujo al resto), pero no afecta a lo hecho si no a los que muestro. Esto implica que el numero de combinaciones para los casos de 4-2, 5-1 y 6-0, son mucho menores:
Las combinaciones del caso 4 decenas + 2 unidades son 38.760 y no 143.080
Las combinaciones del caso 5 decenas + 1 unidades son 177.100 y no 402.895
Con el de 6 decenas + 0 unidades (no hay dígitos en el rango 5-9), se dan muchísimos casos ilegales de las 177.100 9 de cada 10 son ilegales... o bien tienen 00, o bien un valor repetido dos veces. Se puedne filtrar con ligeras modificaciones, abajo lo vuelvo a mencionar cuando llegue el momento...

Código
  1. Friend Class Permutas3_3
  2.    Implements ICombina
  3.  
  4.    Const MAX_COMBINAS As UInt32 = 5005
  5.    Private s_Combinas() As String
  6.  
  7.    Public Sub New()
  8.        Call Enumerar()
  9.    End Sub
  10.  
  11.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  12.        Get
  13.            Return MAX_COMBINAS
  14.        End Get
  15.    End Property
  16.  
  17.    Public Sub Enumerar() Implements ICombina.Enumerar
  18.        s_Combinas = EnumeraComb("ABCDEF", "JKLMNO", MAX_COMBINAS) ' 5005
  19.    End Sub
  20.  
  21.    ' Alfabeto = XYZ   RST
  22.    '  A   B   C   D   E     F   G   H   I   J     K   L   M   N   O
  23.    '  XY  XZ  XR  XS  XT    YX  YZ  YR  YS  YT    ZX  ZY  ZR  ZS  ZT        
  24.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  25.        Dim permuta As String = s_Combinas(Index)
  26.        Dim s(0 To 5) As String
  27.        Dim v As Byte, m As Byte, n As Byte, k As Byte
  28.  
  29.        For k = 0 To 5
  30.            v = (Strings.Asc((permuta.Chars(k))) - 65)
  31.            m = (Decenas(v \ 5) * 10)
  32.            n = (v Mod 5)
  33.  
  34.            If (n < 2) Then
  35.                If (v < 5) Then
  36.                    v = (m + Decenas(n + 1))        ' XY, XZ
  37.                ElseIf (v < 10) Then
  38.                    If (n = 0) Then
  39.                        v = (m + Decenas(n))        ' YX
  40.                    Else
  41.                        v = (m + Decenas(n + 1))    ' YZ
  42.                    End If
  43.                Else
  44.                    v = (m + Decenas(n))            ' ZX, ZY
  45.                End If
  46.            Else
  47.                v = (m + Unidades(n - 2))           ' *R,*S,*T
  48.            End If
  49.  
  50.            If (v < 10) Then s(k) = "0" & v.ToString Else s(k) = v.ToString
  51.        Next
  52.  
  53.        Array.Sort(s)
  54.        Return Join(s, ", ")
  55.    End Function
  56. End Class
  57.  
  58. Friend Class Permutas4_2
  59.    Implements ICombina
  60.  
  61.    Const MAX_COMBINAS As UInt32 = 38760  '143080
  62.    Private s_Combinas() As String
  63.  
  64.    Public Sub New()
  65.        Call Enumerar()
  66.    End Sub
  67.  
  68.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  69.        Get
  70.            Return MAX_COMBINAS
  71.        End Get
  72.    End Property
  73.  
  74.    Public Sub Enumerar() Implements ICombina.Enumerar
  75.        s_Combinas = EnumeraComb("ABCDEF", "OPQRST", MAX_COMBINAS) ' 38760
  76.    End Sub
  77.  
  78.    ' Alfabeto = WXYZ   RS
  79.    ' A   B   C   D   E     F   G   H   I   J     K   L   M   N   O     P   Q   R   S   T
  80.    ' WX  WY  WZ  WR  WS    XW  XY  XZ  XR  XS    YW  YX  YZ  YR  YS    ZW  ZX  ZY  ZR  ZS
  81.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  82.        Dim permuta As String = s_Combinas(Index)
  83.        Dim s(0 To 5) As String
  84.        Dim v As Byte, m As Byte, n As Byte, k As Byte
  85.  
  86.        For k = 0 To 5
  87.            v = (Strings.Asc((permuta.Chars(k))) - 65)
  88.            m = (Decenas(v \ 5) * 10)
  89.            n = (v Mod 5)
  90.  
  91.            If (n < 3) Then
  92.                If (v < 5) Then
  93.                    v = (m + Decenas(n + 1))        ' WX, WY, WZ
  94.                ElseIf (v < 10) Then
  95.                    If (n = 0) Then
  96.                        v = (m + Decenas(n))        ' XW
  97.                    Else
  98.                        v = (m + Decenas(n + 1))    ' XY, XZ
  99.                    End If
  100.                ElseIf (v < 15) Then
  101.                    If (n < 2) Then
  102.                        v = (m + Decenas(n))        ' YW, YX
  103.                    Else
  104.                        v = (m + Decenas(n + 1))    ' YZ
  105.                    End If
  106.                Else
  107.                    v = (m + Decenas(n))            ' ZW, ZX, ZY
  108.                End If
  109.            Else
  110.                v = (m + Unidades(n - 3))           ' *R,*S
  111.            End If
  112.  
  113.            If (v < 10) Then s(k) = "0" & v.ToString Else s(k) = v.ToString
  114.        Next
  115.  
  116.        Array.Sort(s)
  117.        Return Join(s, ", ")
  118.    End Function
  119. End Class
  120.  
  121. Friend Class Permutas5_1
  122.    Implements ICombina
  123.  
  124.    Const MAX_COMBINAS As UInt32 = 177100  '402895
  125.    Private s_Combinas() As String
  126.  
  127.    Public Sub New()
  128.        Call Enumerar()
  129.    End Sub
  130.  
  131.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  132.        Get
  133.            Return MAX_COMBINAS
  134.        End Get
  135.    End Property
  136.  
  137.    Public Sub Enumerar() Implements ICombina.Enumerar
  138.        s_Combinas = EnumeraComb("ABCDEF", "TUVWXY", MAX_COMBINAS) ' 177.100
  139.    End Sub
  140.  
  141.    ' Alfabeto: VWXYZ   R
  142.    ' 01  02  03  04  0?    10  12  13  14  1?    20  21  23  24  2?    30  31  32  34  3?    40  41  42  43  4?
  143.    ' A   B   C   D   E     F   G   H   I   J     K   L   M   N   O     P   Q   R   S   T     U   V   X   Y   Z
  144.    ' VW  VX  VY  VZ  VR    WV  WX  WY  WZ  WR    XV  XW  XY  XZ  XR    YV  YW  YX  YZ  YR    ZV  ZW  ZX  ZY  ZR
  145.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  146.        Dim permuta As String = s_Combinas(Index)
  147.        Dim s(0 To 5) As String
  148.        Dim v As Byte, m As Byte, n As Byte, k As Byte
  149.  
  150.        For k = 0 To 5
  151.            v = (Strings.Asc((permuta.Chars(k))) - 65)
  152.            m = (Decenas(v \ 5) * 10)
  153.            n = (v Mod 5)
  154.  
  155.            If (n < 4) Then
  156.                If (v < 5) Then
  157.                    v = (m + Decenas(n + 1))        ' VW, VX, VY, VZ
  158.                ElseIf (v < 10) Then
  159.                    If (n = 0) Then
  160.                        v = (m + Decenas(n))        ' WV
  161.                    Else
  162.                        v = (m + Decenas(n + 1))    ' WX, WY, WZ
  163.                    End If
  164.                ElseIf (v < 15) Then
  165.                    If (n < 2) Then
  166.                        v = (m + Decenas(n))        ' XV, XW
  167.                    Else
  168.                        v = (m + Decenas(n + 1))    ' XY, XZ
  169.                    End If
  170.                ElseIf (v < 20) Then
  171.                    If (n < 3) Then
  172.                        v = (m + Decenas(n))        ' YV, YW, YX
  173.                    Else
  174.                        v = (m + Decenas(n + 1))    ' YZ
  175.                    End If
  176.                Else
  177.                    v = (m + Decenas(n))            ' ZV, ZW, ZX, ZY
  178.                End If
  179.            Else
  180.                v = (m + Unidades(n - 4))           ' *R
  181.            End If
  182.  
  183.            If (v < 10) Then s(k) = "0" & v.ToString Else s(k) = v.ToString
  184.        Next
  185.  
  186.        Array.Sort(s)
  187.        Return Join(s, ", ")
  188.    End Function
  189. End Class
  190.  
  191. Friend Class Permutas6_0
  192.    Implements ICombina
  193.  
  194.    Const MAX_COMBINAS As UInt32 = 177100
  195.    Private s_Combinas() As String
  196.  
  197.    Public Sub New()
  198.        Call Enumerar()
  199.    End Sub
  200.  
  201.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  202.        Get
  203.            Return MAX_COMBINAS
  204.        End Get
  205.    End Property
  206.  
  207.    Public Sub Enumerar() Implements ICombina.Enumerar
  208.        s_Combinas = EnumeraComb("ABCDEF", "TUVWXY", MAX_COMBINAS)   ' 177.100  
  209.    End Sub
  210.  
  211.    ' Alfabeto: VWXYZ?   _
  212.    ' 00  01  02  03  04    10  11  12  13  14    20  21  22  23  24    30  31  32  33  34    40  41  42  43  44
  213.    ' A   B   C   D   E     F   G   H   I   J     K   L   M   N   O     P   Q   R   S   T     U   V   W   X   Y
  214.    ' VV  VW  VX  VY  VZ    WV  WW  WX  WY  WZ    XV  XW  XX  XY  XZ    YV  YW  YX  YY  YZ    ZV  ZW  ZX  ZY  ZZ
  215.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  216.        Dim permuta As String = s_Combinas(Index)
  217.        Dim s(0 To 6) As String
  218.        Dim v As Byte, m As Byte, n As Byte, k As Byte
  219.  
  220.        For k = 0 To 5  ' el 0 se reserva (caso especial, para comparar un item con el previo)
  221.            v = (Strings.Asc((permuta.Chars(k))) - 65)
  222.            m = (Decenas(v \ 5) * 10)
  223.            n = (v Mod 5)
  224.  
  225.            If (m = n) Then
  226.                s(0) = " --- Combinacion ilegal --- "  ' aparece '00'
  227.            End If
  228.            v = (m + n)
  229.            If (v < 10) Then s(k + 1) = "0" & v.ToString Else s(k + 1) = v.ToString
  230.        Next
  231.  
  232.        Array.Sort(s)
  233.        For k = 1 To 5
  234.            If (s(k) = s(k - 1)) Then
  235.                s(0) = " --- Combinacion ilegal --- " ' un mismo numero aparece 2 veces.
  236.            End If
  237.        Next
  238.  
  239.        Return Join(s, ", ")
  240.    End Function
  241. End Class
  242.  

Realmente la clase 6_0, es casi idéntica a la clase 5_1 (la enumeración es la misma), pero la transformación de los datos difiere. Más aún puesto que alredededor de 9 de cada 10 son ilegales, creo que es inecesario, o al menos filtrar los valores ilegales. Esto es bastante sencillo, simplemente basta reducirlo desde 6 decenas y 0 unidades a 5 decenas y 0 unidades.
Habria que modificar ligeramente la función del botón, que ahora exige que haya 6 dígitos, para aceptar el caso de 5 dígitos y si son todos unidades, derivarlo a la nueva clase y si no error. El otro cambio a apalicar sería en la función de enumeración que yace en el módulo... todas las referencias a la cantidad (0-5), debería aceptar un valor sensible al tamaño que se entre, lo cual se toma del parámetro 'Inicio' (por ejemplo), reclamando su longitud -1, es 6-1 para todas excepto para esta que sería 5-1...
Si te interesa avisas y rehago esta última clase para filtrar las combinaciones ilegales... una captura de ejemplo.


Por ultimo, quizás intereses conocer el número de la combinación seleccionada en un momento dado... para cualquier referencia de interés:
Código
  1.    Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
  2.        Label4.Text = "Indice: " & ListBox1.SelectedIndex.Tostring
  3.    End Sub
  4.  
« Última modificación: 7 Mayo 2021, 15:57 pm por Serapis » En línea

luis456


Desconectado Desconectado

Mensajes: 551



Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #23 en: 8 Mayo 2021, 18:06 pm »

Gracias Serapis

Como te comentado trabajo fuera toda las semana y para mas hoy me han vacunado contra el covid y me tiene un poco nervioso jejej me vacunaron con la estraneca o astranaca o como se llame  🤣 esperare hasta mañana para probar tus códigos (aunque no he trabajado con las clases aparte , pienso que no será difícil ,recuerda que solo soy aficionado pero me afano ya que me encanta la programación  y de simple como es el titulo del post ( Ejercicio básico de combinaciones )  esto ya es un bicho grande pero yo encantado ya que he visto mas posibilidades de mejorar los cálculos para encima otros sistemas de loterías pero ese es otro tema (para depues jejej)

te aviso
Luis
En línea

Que tu sabiduria no sea motivo de Humillacion para los demas
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #24 en: 8 Mayo 2021, 21:13 pm »

Tranquilo... esto no es una red social, donde la gente (parece) exigir que le contesten no tardando más de no se qué cuanto tiempo (so pena de enfadarse). Cada uno a su ritmo...

Hice al final también el filtrado para los de 6_0, de dos maneras distintas...
Una de ellas simplemente ignora añadir al listbox, las entradas ilegales (al final quedna así alrededor de la mitad), el otro modo de fitrado es tratarlo como lo que son solo 5 dígitos, arroja unas 15500 combinaciones, pero no lo veo interesante por que contiene así solo 5 combinaciones (pero quien sabe si un oquisiera aparte poner el 6º manualmente).

Mañana lo comprimo en un zip y lo subo a alguna página de descarga...
En línea

luis456


Desconectado Desconectado

Mensajes: 551



Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #25 en: 8 Mayo 2021, 22:59 pm »

Tranquilo... esto no es una red social, donde la gente (parece) exigir que le contesten no tardando más de no se qué cuanto tiempo (so pena de enfadarse). Cada uno a su ritmo...

Hice al final también el filtrado para los de 6_0, de dos maneras distintas...
Una de ellas simplemente ignora añadir al listbox, las entradas ilegales (al final quedna así alrededor de la mitad), el otro modo de fitrado es tratarlo como lo que son solo 5 dígitos, arroja unas 15500 combinaciones, pero no lo veo interesante por que contiene así solo 5 combinaciones (pero quien sabe si un oquisiera aparte poner el 6º manualmente).

Mañana lo comprimo en un zip y lo subo a alguna página de descarga...

Gracias y para esta Hora todavía sigo vivo 😃 ya veremos mañana
saludos
Luis



En línea

Que tu sabiduria no sea motivo de Humillacion para los demas
luis456


Desconectado Desconectado

Mensajes: 551



Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #26 en: 9 Mayo 2021, 16:52 pm »

Hola Serapis

Bueno pase mala noche ya que me dio fiebre esta vacuna y ahora tengo un super catarro :( me he puesto un rato con el programa pero no me aclaro que es lo que tengo que hacer o poner para armarlo pensé me seria fácil jeje .me lo llevo al trabajo a ver si por la noche lo puedo terminar

saludos
Luis
En línea

Que tu sabiduria no sea motivo de Humillacion para los demas
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #27 en: 10 Mayo 2021, 17:01 pm »

...'armar' el programa... bueno, se supone que quien pide tiene alguna idea básica de lo que es un proyecto en el lenguaje que trata... y con leves explicaciones debería entenderlo bien. De todos modos, lo he comprimido en su carpeta y lo subo a una página de descargas.

También he añadido la clase para el caso de 5 decenas y 0 unidades, es decir para introducir solo 5 dígitos (los que pueden actuar como decenas): 0,1,2,3,4 y generar sus permutaciones, y la 6ª combinación introducirla manualmente...
El código de esta clase, va al final del fichero 'form1.vb' y por supuesto, tras incluirlo, s eprecisa crear una instancia para invocarlo, etc... (mira el código del proyecto que adjunto, si tienes dudas)
Código
  1. Friend Class Permutas5_0
  2.    Implements ICombina
  3.  
  4.    Const MAX_COMBINAS As UInt32 = 15504
  5.    Private s_Combinas() As String
  6.  
  7.    Public Sub New()
  8.        Call Enumerar()
  9.    End Sub
  10.  
  11.    Public ReadOnly Property Cantidad As UInteger Implements ICombina.Cantidad
  12.        Get
  13.            Return MAX_COMBINAS
  14.        End Get
  15.    End Property
  16.  
  17.    Public Sub Enumerar() Implements ICombina.Enumerar
  18.        s_Combinas = EnumeraComb("ABCDE", "PQRST", MAX_COMBINAS)   ' 15504
  19.    End Sub
  20.  
  21.    ' Alfabeto: VWXYZ
  22.    ' 01  02  03  04    10  12  13  14    20  21  23  24    30  31  32  34    40  41  42  43
  23.    ' A   B   C   D     E   F   G   H     I   J   K   L     M   N   O   P     Q   R   S   T
  24.    ' VW  VX  VY  VZ    WV  WX  WY  WZ    XV  XW  XY  XZ    YV  YW  YX  YZ    ZV  ZW  ZX  ZY
  25.    Public Function Tranformar(ByVal Index As Integer, ByRef Decenas() As Byte, ByRef Unidades() As Byte) As String Implements ICombina.Tranformar
  26.        Dim permuta As String = s_Combinas(Index)
  27.        Dim s(0 To 4) As String
  28.        Dim v As Byte, m As Byte, n As Byte, k As Byte
  29.  
  30.        For k = 0 To 4
  31.            v = (Strings.Asc((permuta.Chars(k))) - 65)
  32.            m = (Decenas(v \ 4) * 10)
  33.            n = (v Mod 4)
  34.  
  35.            If (v < 4) Then
  36.                v = (m + Decenas(n + 1))        ' VW,VX, VY, VZ
  37.            ElseIf (v < 8) Then
  38.                If (n = 0) Then
  39.                    v = (m + Decenas(n))        ' WV
  40.                Else
  41.                    v = (m + Decenas(n + 1))    ' WX, WY, WZ
  42.                End If
  43.            ElseIf (v < 12) Then
  44.                If (n < 2) Then
  45.                    v = (m + Decenas(n))        ' XV, XW
  46.                Else
  47.                    v = (m + Decenas(n + 1))    ' XY, XZ
  48.                End If
  49.            ElseIf (v < 16) Then
  50.                If (n < 3) Then
  51.                    v = (m + Decenas(n))        ' YV, YW, YX
  52.                Else
  53.                    v = (m + Decenas(n + 1))    ' YZ
  54.                End If
  55.            Else
  56.                v = (m + Decenas(n))            ' ZV, ZW, ZX, ZY
  57.            End If
  58.  
  59.            If (v < 10) Then s(k) = "0" & v.ToString Else s(k) = v.ToString
  60.        Next
  61.  
  62.        Array.Sort(s)
  63.        Return Join(s, ", ")
  64.    End Function
  65. End Class
  66.  

Nota que puede ser optimizado para ganar en velocidad de cálculo a cambio de complicar un poco más el algoritmo yacente en la función 'Transformar'.
Dado que una combinación y la siguiente suele variar la mayor parte de las veces solo 1 valor de los 6 que tiene la combinación, retener el array 's' (hacerlo estático) y calcular solo el valor o valores que cambian. Pero en lo que a mí respecta te lo dejo así, queda a tu esfuerzo optimizarlo si es de tu interés y preferencia. En general (no siempre) cualquier optimización aplicada tiende a oscurecer el mecanismo del algoritmo, lo que dificulta su entendimiento.

Descarga del proyecto: https://workupload.com/file/Nu6FVTcfH2g 15'11Kb.
Cuando lo descarges y abras verás en cada fichero el código que adjunta.
Los 3 ficheros principales son: Module1.vb, Interface1.vb y Form1.vb que son los que contienen el código y por tanto los que tienes que mirar (o copy-paste). El proyecto exige otros más para poder arrancar en el IDE de VS.
(adjunté, la operatoria de 'reset', que explicaba mensajes más arriba, pero igualmente puedes ignorarlo al menos de momento).
En línea

luis456


Desconectado Desconectado

Mensajes: 551



Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #28 en: 11 Mayo 2021, 22:27 pm »

 ;-) ;-) ;-) ;-)

Perfecto Serapis funciona de maravilla te has brillado con este programa, aunque claro es inasumible apostar tal cantidad de apuestas ,he echo algunas apuestas "Virtuales " y si las hubiéramos jugados ya seriamos millonarios  :silbar:  pero no es motivo de desesperanza ya que es cuestión de aplicar variados filtros, algo de estadística y otros métodos personales  (aunque esta comprobado que las estadísticas para las loterías no sirven, porque será ??? )

Bien ahora es cuestión de hacer un menú ,guardar apuestas generadas por ejemplo para poder comparar resultados y aciertos con el sorteo (para no hacerlo a mano para eso esta la programación jejje) quien habrá dicho eso  :rolleyes: algunos filtros de reducción de apuestas etc ete.

Bueno a pesar de que todavía ando con los efectos de la vacuna (me callo fatal esa *****) ya creo que no muero y pienso que este programa vale la pena hacerlo muy completo y puede ser un buen programa y muy eficaz solo es cuestión de ideas y de cálculos .

Para el dia de hoy este post lo han visto 4,360 veces me imagino que hay expectativas sobre el desarrollo del programa jejje solo que no veo aportes e ideas.

Bueno seguiré probándolo y vemos que tal

De nuevo Gracias Serapis

ya te contare

Luis







 
En línea

Que tu sabiduria no sea motivo de Humillacion para los demas
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.391


Ver Perfil
Re: Ejercicio básico de combinaciones
« Respuesta #29 en: 12 Mayo 2021, 01:11 am »

La bonoloto, no se presta a muchas estadísticas, por la enorme cantidad de permutaciones que tolera, y como solo se juega una vez a la semana... pués aunque reúnas los sorteos de 20 años, no creo que dé para sacar conclusiones.

En los casinos (por ejemplo), pequeños fallos en la fabricación o montaje de mesas de apuestas, y la puesta en escena de otros juegos, pueden manifestar 'debilidades', precisamente porque se juegan mas apuestas en un solo día que la bonoloto en todo un año...

Si hay 'debilidades' en el sistema, puede ser atacado matemáticamente.

Mi cuñado solía jugar a la bonoloto, yo nunca he jugado, por lo que aunque conozco el juego, no los detalles de las reglas. En tú eliges 6 números y deben cincidir todos, entonces jugar alguna número más, reduce las posibilidades combinatorias (aumentan la sposibilidades de acertar), porque siguen bastando 6 combinaciones en una apuesta de 7 números, pero como no me sé las reglas, y por ello no sé si es posible apostar 7 números y si en tal caso (el precio de tal apuesta) equivale al número de apuestas que representan... y si por tanto su coste es equivalente a las apuestas que representan, si no es así, cuantos más números se apostasen aumentarían las posibilidades (de acierto) en menor cantía económica a las (posibilidades de) reducciones de permutaciones resultantes... pero, inclsuo así, es probable que el coste por apuesta unitaria impida señalar números grandes de apuestas, pués el coste total pueda llegar a ser prohibitivo par ale bolsillo.

El número de combinaciones de la bonoloto (para apuestas que exigen 6 combinacones elegibles) es de: 49 * 48 * 47 * 46 * 45 * 44, ahora bien ahí no se filtra las combinaciones que resultan de la misma pero en diferente orden, luego queda dividirla entre 1 * 2 * 3 * 4 * 5 * 6, que supone divir esas más 10 mil millonres 720 veces, lo que siguen dando una cifra elevada pero asequible de 'mantener' a raya.

Yo he sido siempre más de quinielas de fútbol... siendo resultado de una 'actividad humana', las estadisticas son más fáctibles de reflejar la realidad de los equipos (siempre que ellos mismos no apuesten y por ello falsifiquen resultados, seguro que te acuerdas que se ha dado más de un caso incluso con detenciones por delitos de este tipo, no solo en España, también en otros países)...

De todos modos, lo que a mi me apasiona de este tipo de juegos son las matemáticas tras ellos.
Tengo una intuición en la quiniela que aún no me he demostrado (a favor o en contra), que más o menos resumo así: "elegidas 2187 apuestas específicas (no cualesquiera, evidentemente), garantizan siempre un acierto de 14 y varios de 13, amén de los de 12 y 11...". La demostración por exhaustación es inviable en tiempo computacional, así que requiere mucho esfuerzo de cálculo para reducir por combinatoria la búsqueda de tales apuestas (algún día me pondré con ello  :silbar: :silbar: :silbar:).

Para cualquier interesado en la combinatoria, deben verlo como un sistema que autocontiene o da soporte a una infinitud de bases numéricas con condiciones más o menos 'caprichosas'. Pero que, conocidas tales condiciones uno puede enumerar correlativamente en la base decimal (1,2,3,4,5,6...) para referirse al número enésimo en dicha base numérica caprichosa, vamos como cualquier otra base numérica, y por tanto poder elaborar una fórmula para tomando la enésima combinación requerida (el enésimo número en esa base numérica), obtener el equivalente con los datos que uno pretende que le represente... vamos una abstracción igual que usamos los números para contar monedas, personas, y todo en general. Es justamente la forma en que los algoritmos están representados en este proyecto, donde cada uno (por ser condionantes distintos), mantienen un alfabeto propio, al ser representados por bases numéricas distintas. Un condicionante es la no repetición de elementos, algo deseable a filtrar siempre que sea suficiente mantener un sola copia de dicho elemento, de otro modo el número de permutaciones se dispara...

Baste ver la difrencia de combinaciones totales de la bonoloto, 10.068.347.520 frente a las mismas sin repetición: 13.983.816, o dicho de otra manera dada una combinación cualquiera, por ejemplo: 05, 11, 18, 25, 37, 41, se pueden reordenar de 720 maneras distintas, pero de cara a la bonoloto, son la misma apuesta que si alguien decide apostar: 37, 18, 25, 41, 05, 11.
Merece la pena crear un fichero con todas esas combinaciones de casi 14millones de apuestas distintas?. La respuesta se autoresponde sola: Solo si uno no sabe luego traducir de la base numérica 13983816 a la combinación específica enumerada, supongamos que la combinación antedicha fuera la 3.100.000ª combinación de esa base numérica, es decir,
Código:
string = funcion GetCombinacion(entero32 Index)
    string Combinacion

   return Bonoloto(13983816, index)
fin funcion

entero32 index = 3100000
string comb = GetCombinacion(index)
imprimir "El resultado es: " + comb
//Salida:
"El resultado es: 05, 11, 18, 25, 37, 41"
Por lo que, si uno sabe traducir un índice de una base numérica en el valor deseado, no es necesario generar un fichero con todas las combinaciones posibles (lo mismo que con las contraseñas, que es 'mas de los mismo', bases numéricas con condicionantes más o menos capichosos), es suficiente saber el número de combinaciones que se generan. Aunque normalemente tener las combinaciones totales, puede acelerar el cálculo cuando se trata de tomar muchas combinaciones contiguas, o cambia el modo de representación de la salida (en el ppppprograma cambian los dígitos a jugar, peor mantiene una combinación equivalente, es decir son 'instancias', especifidades d ela abstracción representada en la enumeración que es a fin de cuentas la base numérica subyacente), aunque para ello deben estar en una codificación intermedia (a medio hacer entre la enumeración consecutiva y el objetivo final), de otro modo tener un fichero con: 0, 1,2,3,4,5... 10002, 10003, 10004... 13983813, 13983814, y 13983815. Pués resulta obvio que es ridículo basta conocer que esi el numero máximo de combinaciones son 13983816, el rango quedará definido entre 0 y 13983816-1, luego puede mantenerse en un programa como constante... que es lo que se hace en el programa.

Saludos.
« Última modificación: 12 Mayo 2021, 01:26 am por Serapis » En línea

Páginas: 1 2 [3] 4 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ejercicio: las posibles combinaciones de una lista [python]
Ejercicios
Ragnarok 5 18,883 Último mensaje 9 Septiembre 2009, 22:16 pm
por do-while
Ayuda en ejercicio basico
.NET (C#, VB.NET, ASP)
The_Saint 2 2,620 Último mensaje 16 Abril 2013, 20:27 pm
por The_Saint
Ejercicio básico Python
Programación General
srg 3 2,921 Último mensaje 30 Octubre 2013, 01:46 am
por Mitsu
Ayuda con ejercicio basico en C « 1 2 »
Programación C/C++
MartaR95 11 7,083 Último mensaje 12 Diciembre 2016, 01:14 am
por MAFUS
Ejercicio Básico de Operadores en C
Programación C/C++
palacio29 4 2,870 Último mensaje 14 Febrero 2017, 20:50 pm
por ivancea96
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines