Ejercicio básico de combinaciones

Iniciado por luis456, 25 Abril 2021, 11:21 AM

0 Miembros y 3 Visitantes están viendo este tema.

Serapis

Ok... es algo muy distinto a lo que yo entendí.

Tu quieres ¿todas? las permutaciones de 2 grupos de cifras.
Donde el primer grupo está formado por las 2 primeras cifras, y el segundo por las otras 4 cifras.
Aún me queda otra duda, a ver si me la resuelves antes de que cierre la página...

A - ¿El primer grupo solo y siempre puede formar parte en las decenes y el segundo solo y siempre de las unidades (o viceversa, pero solo y siempre)?

B - ¿... o pueden igulamente ser intercambiados mientras el dígito en la unidad sea de un grupo distinto al dígito en la decena?. Esto si sería de verdad 'todas' las permutaciones posibles.

K-YreX

Cita de: Serapis en  1 Mayo 2021, 22:03 PM
Yo no veo que 'se complique'... en realidad hay una optimización, que simplemente añade una sola línea de código y modifica ligeramente 2 lineas... esperaba que cuando ejecutara los cambios si los entendía, pudiera él mismo intentarlo (es algo obvio) o al menos preguntar...
No me refería a que se complicase el código (que entiendo que el tuyo es más extenso por haber incluido código de la interfaz) sino a lo de mantener la distancia entre los números y generar números con dígitos que no están entre los introducidos.

Al final ha resultado que yo tampoco lo estaba terminando de entender pero creo que ahora ya sí.
Cita de: Serapis en  1 Mayo 2021, 23:20 PM
A - ¿El primer grupo solo y siempre puede formar parte en las decenes y el segundo solo y siempre de las unidades (o viceversa, pero solo y siempre)?

B - ¿... o pueden igulamente ser intercambiados mientras el dígito en la unidad sea de un grupo distinto al dígito en la decena?. Esto si sería de verdad 'todas' las permutaciones posibles.
A mí entender, una vez tienes todos los grupos posibles (menores a 49) de 2 dígitos con los dígitos dados, hay que crear digamos filas combinando 6 de esos grupos.


Estando ahora en lo cierto, según mis códigos anteriores ya teníamos en numerosGenerados todos los números menores a 49 generados. Ahora habría que combinar dichos números para crear los nuevos grupos (cada uno formado por 6 números de los generados).
Pongamos el siguiente caso (cogido de uno de los códigos anteriores):

digitos = { 1, 4, 5, 7, 8, 9 }
numerosGenerados = { 11, 14, 15, 17, 18, 19, 41, 44, 45, 47, 48, 49 }

Ahora queremos crear grupos del tipo: { X1, X2, X3, X4, X5, X6 } donde cada Xi es un número perteneciente a numerosGenerados.
Podemos ver que X1 nunca podrá ser 44 o mayor porque entonces nos faltarían números para completar el grupo.
De la misma manera X2 nunca podrá 11 (porque entonces cuál sería X1??) ni 45 o mayor por lo mismo que antes.
Haciendo el mismo cálculo con cada uno podemos sacar el siguiente código:
Código (csharp) [Seleccionar]

List<List<int>> gruposGenerados = new List<List<int>>();
int elementosPorGrupo = 6;

for(int i = 0; i < numerosGenerados.Count - elementosPorGrupo + 1; ++i)
for(int j = i + 1; j < numerosGenerados.Count - elementosPorGrupo + 2; ++j)
for(int k = j + 1; k < numerosGenerados.Count - elementosPorGrupo + 3; ++k)
for(int l = k + 1; l < numerosGenerados.Count - elementosPorGrupo + 4; ++l)
for(int m = l + 1; m < numerosGenerados.Count - elementosPorGrupo + 5; ++m)
for(int n = m + 1; n < numerosGenerados.Count - elementosPorGrupo + 6; ++n)
gruposGenerados.Add(new List<int> {numerosGenerados[i], numerosGenerados[j], numerosGenerados[k], numerosGenerados[l], numerosGenerados[m], numerosGenerados[n]});

PD: El código se puede simplificar pero así creo que es más fácil de entender.

SALIDA:

11 14 15 17 18 19
11 14 15 17 18 41
11 14 15 17 18 44
11 14 15 17 18 45
11 14 15 17 18 47
11 14 15 17 18 48
11 14 15 17 18 49
11 14 15 17 19 41
11 14 15 17 19 44
11 14 15 17 19 45
11 14 15 17 19 47
11 14 15 17 19 48
11 14 15 17 19 49
11 14 15 17 41 44
11 14 15 17 41 45
11 14 15 17 41 47
11 14 15 17 41 48
11 14 15 17 41 49
...
18 44 45 47 48 49
19 41 44 45 47 48
19 41 44 45 47 49
19 41 44 45 48 49
19 41 44 47 48 49
19 41 45 47 48 49
19 44 45 47 48 49
41 44 45 47 48 49
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

Serapis

Cita de: K-YreX en  2 Mayo 2021, 14:28 PM
No me refería a que se complicase el código (que entiendo que el tuyo es más extenso por haber incluido código de la interfaz) sino a lo de mantener la distancia entre los números y generar números con dígitos que no están entre los introducidos.
Ok... creí que te referías al código.

Cita de: K-YreX en  2 Mayo 2021, 14:28 PM
Al final ha resultado que yo tampoco lo estaba terminando de entender pero creo que ahora ya sí.A mí entender, una vez tienes todos los grupos posibles (menores a 49) de 2 dígitos con los dígitos dados, hay que crear digamos filas combinando 6 de esos grupos.
Sí. Yo entendí una cosa claramente al comienzo, pero cuando luego dijo una frase, que 'no encajaba', entonces percibí que podría estar queriendo algo distinto, aunque no tan distinto.
Resulta confuso, colocar dos parámetros con distinta aplicación semántica como si fueran uno solo y mismo.
Aún quedaban algunas dudas anoche, que no respondió... Hace un rato al volver a mirar, veo en los ejemplos son lo suficientemente explícitos para deducir que finalmente quiere formar las dos combinaciones que faltan poniendo como unidad uno de los valores de las decenas si es preciso...




Yo lo he resuleto de la siguiente manera (hay varias, una es como ha hecho K-YreX, con varios bucles anidados, en cada bucle se opera solo con el carácter en la posición solicitada)...

Sean el Alfabeto los dos grupos de valores, llamémoslo: X,Y,  y   R,S,T,U
Solo hay 8 pares de combinaciones: Resultado de combinar cada uno del 'Grupo de Decenas' con cada uno del 'Grupo de Unidades'
   XR, XS, XT, XU  (0,1,2,3)
   YR, YS, YT, YU  (4,5,6,7)
Más las 2 combinaciones de intercambiar de posicion los valores del 'grupo de Decimales'
   XY, YX       (8,9) 
Cada par de esos 10 se enumeran ahora como 0-9 (como se ve a su derecha), el orden seguido iniciamente era el ahí mostrado (0,1,2,3), pero luego para mantener un orden lo más exacto posible a como aparece en el ejemplo de muestra, en el código se ha variado el orden (he dejado comentado (dos conjuntos distintos)). Ahora, por tanto nos basta reconocer cada par con 1 solo carácter en el rango 0-9.

La cantidad de combinaciones totales sería: (10*9*8*7) * (6*5) = 151.200, ahora bien ese es el caso de no poner restricciones a X e Y (como solo toman valores 0-4), se recalcula como: (10*9*8*7) * (5*4) = 5040 * 20 = 100.800 Esa cifra tampoco es definitiva, porque cuando X ó Y son 0, ni R, ni S, ni T, ni U pueden valer 0, luego habría que descontar algunas... como el problema no es calcular dicho valor exacto, lo dejamos ahí que es bastante aproximado.
Ahora, como las combinaciones son tomadas de 6 en 6, el numero de combinaciones con esos 10 pares tomados de 6 en 6 son solo: 210.
Primero calculamos esas combinaciones que permanecerán estáticas en un array durante la vida del programa... y luego con los valores recibidos lo que se hará es transformar cada una de esas combinaciones conforme a los valores recibidos.

El código para mostrar en el listado esas 210 combinaciones se deja comentado (con un botón aparte una vez abierta la ventana se pueden mostrar en el listbox, pero vamos resumiendo van desde 012345 hasta 456789, ninguna de las combinaciones a partir de la inicial es menor que la previa, y así se llega a todas ellas).

Ahora el código con breves explicaciones (a las ya dadas) y alguna captura...
La ventana recurre a una clase, que crea las 210 permutaciones y que luego dado un índice realiza la transformación.
El código de la interfaz, trata simplemente de tomar el string del textbox y convertirlo en los parámetros que debe recibir la función de transformación. No se ha hecho nada especial para verificar que el string del textbox sea correcto, básicamente cada valor debe debe estar separado por una coma (opcionalmente con espacios).

Código (vbnet) [Seleccionar]

Imports System.Text

Public Class Form1
    Private Permuta As New Permutaciones
    Private Decenas(2) As Byte, Unidades(4) As Byte

   
    ' El botón de la interfaz...
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Nums() As String, txt As String
        Dim k As UInt16

        txt = TextBox1.Text.Replace(" ", "")
        Nums = txt.Split(",")
        If (Nums.Length = 6) Then
            ' crear los parámetros para la funcion de Transformacion:
            Decenas(0) = System.Byte.Parse(Nums(0))
            Decenas(1) = System.Byte.Parse(Nums(1))
            For k = 2 To 5
                Unidades(k - 2) = System.Byte.Parse(Nums(k))
            Next

            ListBox1.Items.Clear()
            For j = 0 To Permuta.Cantidad - 1
                ListBox1.Items.Add(Permuta.Transforma(j, Decenas, Unidades))
            Next
            Label3.Text = "Cantidad en lista: " & ListBox1.Items.Count.ToString
        Else
            MessageBox.Show("No, no no... Debe haber 6 y solo 6 numeros, separados por 1 coma...")
        End If
    End Sub



Private Class Permutaciones
        Const MAX_COMBINAS As UInt16 = 210
        Private s_Combinas(MAX_COMBINAS) As UInt32 

        Public ReadOnly Property Cantidad As UInt16
            Get
                Return MAX_COMBINAS
            End Get
        End Property

        Public Function Transforma(ByVal Indice As UInt16, ByVal Dec() As Byte, ByVal Uni() As Byte) As String
            Dim permuta As UInt32 = s_Combinas(Indice)
            Dim s As String = "", valor As String = ""
            Dim x As Byte = 0, k As Byte

            For k = 0 To 5
                x = (permuta Mod 10)
                permuta \= 10

                Select Case x
                    ' forma C en que quedan ordenados más aproximado al ejemplo de muestra...
                    Case 0 : x = ((Dec(0) * 10) + Dec(1))                   
                    Case 1 To 4 : x = ((Dec(0) * 10) + Uni(x - 1))
                    Case 5 To 8 : x = ((Dec(1) * 10) + Uni(x - 5))
                    Case 9 : x = ((Dec(1) * 10) + Dec(0))

                    ' Otra forma B en que quedan ordenados...
                        'Case 0 : x = ((Dec(0) * 10) + Dec(1))
                        'Case 1 : x = ((Dec(1) * 10) + Dec(0))
                        'Case 2 To 5 : x = ((Dec(0) * 10) + Uni(x - 2))
                        'Case 6 To 9 : x = ((Dec(1) * 10) + Uni(x - 6))

                    ' Otra forma A en que quedan ordenados...
                        'Case 0 To 3 : x = ((Dec(0) * 10) + Uni(x))
                        'Case 4 To 7 : x = ((Dec(1) * 10) + Uni(x - 4))
                        'Case 8 : x = ((Dec(0) * 10) + Dec(1))
                        'Case 9 : x = ((Dec(1) * 10) + Dec(0))
                End Select

                If (x < 10) Then s = "0" & x.ToString Else s = x.ToString
                valor = (s & ", ") & valor
            Next

            Return valor
        End Function


        ' Genera todas las permutaciones posibles (210) en formato numerico.
        ' Alfabeto = X,Y,   R,S,T,U
        ' solo hay 8 pares de combinaciones: Resultado de combinar cada uno del GrupoDec con cada uno del GrupoUni
        '   XR, XS, XT, XU  (0,1,2,3)
        '   YR, YS, YT, YU  (4,5,6,7)
        '  Más las 2 combinaciones de intercambiar de posicion los valores del 'grupoDec'
        '   XY, YX          (8,9) 
        ' Cada par de esos 10 se enumeran ahora como 0-9 (usando una solo caracter)
        ' Ahora el numero de combinaciones con esos 10 pares tomados de 6 en 6 son: 210
        Public Sub New()
            Dim combina As UInteger = 12345       ' combinacion inicial
            Dim final As UInteger = 456789           '  combinación final
            Dim k As UInt16
            Dim digitos(0 To 5) As Byte, n As Byte  ' control de límite de cada dígito.

            For k = 0 To 5
                digitos(k) = k
            Next

            k = 0
            Do
                s_Combinas(k) = combina
                If (digitos(5) = 9) Then
                    n = 4
                    Do While digitos(n) = digitos(n + 1) - 1
                        n -= 1
                    Loop
                    digitos(n) += 1
                    For n = n + 1 To 5
                        digitos(n) = digitos(n - 1) + 1
                    Next
                    combina = 0
                    For n = 0 To 5
                        combina += digitos(n) * (10 ^ (5 - n))
                    Next
                Else
                    combina += 1 : digitos(5) += 1
                End If
                k += 1
            Loop While (combina < final)
            s_Combinas(k) = combina
        End Sub

        'Public ReadOnly Property Permuta(ByVal X As UInt16)
        '    Get
        '        Return s_Combinas(X)
        '    End Get
        'End Property
    End Class

' Mostras la lista de permutaciones en el listbox.... va en conjunto con la propiedad 'Permuta' de la clase permutaciones.
'Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    '    Dim k As UInt16, j As UInt32, s As String = ""

    '    ListBox1.Items.Clear()
    '    For k = 0 To Permuta.Cantidad - 1
    '        j = (Permuta.Permuta(k))
    '        If (j < 123456) Then s = "0" & j.ToString Else s = j.ToString
    '        ListBox1.Items.Add(s)
    '    Next
    'End Sub
End Class


Las combinaciones numéricas podrían guardarse a fichero una vez, borrar la función actual para ser remplazada por una que se lea de fichero (requiere menos líneas, pero no merece el esfuerzo solo para ahorrarse una docena de líneas y dejar opaco como se han generado dichas combinaciones)...

X e Y, no deberían ser ambos 0, y si uno de ellos es 0 y otro del otro grupo es 0, habrá combinaciones ilegales (no se filtran, pero es fácil reconocerlas porque un valor de dicha combinación tendrá el valor '00', que como se sabe no forma parte de las 'apuestas' que permite la 'primitiva' (01-49).
Se podría mejorar la interfaz, poniendo sendos controles para cada dígito, para permitir que cada variable tome un valor en el rango posible (X e y en el rango 0-4 y RSTU en el rango 0-9) y limitarlo de forma exclusiva, de modo que cuando se elija por ejemplo para R el 5, se desactive para S,T y U el 5, etc... así no puede haber valores repetidos.
Pero vamos si quien lo usa lo hace con criterio, se supone que sabrá evitar valores ilegales.... queda como ejercicio del interesado cualquier cambio en la simple intrfaz, o al menos no tomar como válidas las combinaciones donde aparezca el par no legal '00', lo que es trivial... y básicamente no merece esfuerzo invertir en modificar la interfaz para ello (otra cosa es que debiera pasarse a un tercero sin idea de lo que debe y no debe introducir).

Y  finalmente una captura con el ejemplo de muestra de Luis456: 2, 3, 5,6,8, 9

luis456

Gracias Serapis por tu ayuda he estado probando el código y bien vamos Bien jejje pero (siempre hay un pero ) no quiero que me hagas todo el trabajo ,solo explícame como funcionan algunas cosas para yo modificarlo , en el ejemplo anterior usas los números que pongo de ejemplo  " 2, 3, 5,6,8, 9 " pero estos números cambian después de cada sorteo (después os explicare como los saco) según voy entiendo el código este toma solo los dos primeros y los combina con el resto ,bien el tema es que como sabemos las decenas son hasta el cuatro y a veces tendría que introducir ejemplo ( 1 , 2 ,4 - 5,7,8 ) y ahora el programa para las combinaciones no toma el cuatro solo el 1 y 2 , he puesto un botón para limpiar y poder hacer pruebas y el código va de maravilla ,pongo el código y algunas observaciones  a ver que te parece ?

Código (vbnet) [Seleccionar]
Imports System.Text



Public Class Form1
    Private Permuta As New Permutaciones
    Private Decenas(2) As Byte, Unidades(4) As Byte


    ' El botón de la interfaz...
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Nums() As String, txt As String
        Dim k As UInt16

        txt = TextBox1.Text.Replace(" ", "") ' <<<<<<<<<<<<<<   ACA CAMBIAN LOS NUMEROS NUNCA SON LOS MISMOS ...Y DEBE TOMAR HASTA EL DIGITO 4  SABEMOS QUE LAS DECENAS SON 0 1 2 3 Y 4
        Nums = txt.Split(",")
        If (Nums.Length = 6) Then
            ' crear los parámetros para la funcion de Transformacion:
            Decenas(0) = System.Byte.Parse(Nums(0))
            Decenas(1) = System.Byte.Parse(Nums(1))
            For k = 2 To 5
                Unidades(k - 2) = System.Byte.Parse(Nums(k))
            Next

            ListBox1.Items.Clear()
            For j = 0 To Permuta.Cantidad - 1
                ListBox1.Items.Add(Permuta.Transforma(j, Decenas, Unidades))
            Next
            Label1.Text = "Cantidad en lista: " & ListBox1.Items.Count.ToString
        Else
            MessageBox.Show("No, no no... Debe haber 6 y solo 6 numeros, separados por 1 coma...")
        End If
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    ' FUNCION LIMPIAR LISTBOSX...
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        For Each obj As Control In Me.Controls
            If (TypeOf obj Is TextBox) Then
                obj.Text = ""
            End If
            If (TypeOf obj Is GroupBox) Then
                For Each caja As Control In obj.Controls
                    If (TypeOf caja Is TextBox) Then
                        caja.Text = ""
                    End If
                Next
            End If
            ListBox1.Items.Clear()


        Next
    End Sub

    Private Class Permutaciones
        Const MAX_COMBINAS As UInt16 = 210
        Private s_Combinas(MAX_COMBINAS) As UInt32

        Public ReadOnly Property Cantidad As UInt16
            Get
                Return MAX_COMBINAS
            End Get
        End Property

        Public Function Transforma(ByVal Indice As UInt16, ByVal Dec() As Byte, ByVal Uni() As Byte) As String
            Dim permuta As UInt32 = s_Combinas(Indice)
            Dim s As String = "", valor As String = ""
            Dim x As Byte = 0, k As Byte

            For k = 0 To 5
                x = (permuta Mod 10)
                permuta \= 10

                Select Case x
                    ' forma C en que quedan ordenados más aproximado al ejemplo de muestra...
                    Case 0 : x = ((Dec(0) * 10) + Dec(1))
                    Case 1 To 4 : x = ((Dec(0) * 10) + Uni(x - 1))
                    Case 5 To 8 : x = ((Dec(1) * 10) + Uni(x - 5))
                    Case 9 : x = ((Dec(1) * 10) + Dec(0))

                        ' Otra forma B en que quedan ordenados...
                        'Case 0 : x = ((Dec(0) * 10) + Dec(1))
                        'Case 1 : x = ((Dec(1) * 10) + Dec(0))
                        'Case 2 To 5 : x = ((Dec(0) * 10) + Uni(x - 2))
                        'Case 6 To 9 : x = ((Dec(1) * 10) + Uni(x - 6))

                        ' Otra forma A en que quedan ordenados...
                        'Case 0 To 3 : x = ((Dec(0) * 10) + Uni(x))
                        'Case 4 To 7 : x = ((Dec(1) * 10) + Uni(x - 4))
                        'Case 8 : x = ((Dec(0) * 10) + Dec(1))
                        'Case 9 : x = ((Dec(1) * 10) + Dec(0))
                End Select

                If (x < 10) Then s = "0" & x.ToString Else s = x.ToString
                valor = (s & ", ") & valor
            Next

            Return valor
        End Function


        ' Genera todas las permutaciones posibles (210) en formato numerico.
        ' Alfabeto = X,Y,   R,S,T,U
        ' solo hay 8 pares de combinaciones: Resultado de combinar cada uno del GrupoDec con cada uno del GrupoUni
        '   XR, XS, XT, XU  (0,1,2,3)
        '   YR, YS, YT, YU  (4,5,6,7)
        '  Más las 2 combinaciones de intercambiar de posicion los valores del 'grupoDec'
        '   XY, YX          (8,9) 
        ' Cada par de esos 10 se enumeran ahora como 0-9 (usando una solo caracter)
        ' Ahora el numero de combinaciones con esos 10 pares tomados de 6 en 6 son: 210
        Public Sub New()
            Dim combina As UInteger = 12345       ' combinacion inicial -----------NO ENTIENDO ESTO YA QUE LOS NUMEROS DE LAS DECENAS NO PUEDEN PASAR DEL 4
            Dim final As UInteger = 456789           '  combinación final --------------???????????????
            Dim k As UInt16
            Dim digitos(0 To 5) As Byte, n As Byte  ' control de límite de cada dígito.

            For k = 0 To 5
                digitos(k) = k
            Next

            k = 0
            Do
                s_Combinas(k) = combina
                If (digitos(5) = 9) Then
                    n = 4
                    Do While digitos(n) = digitos(n + 1) - 1
                        n -= 1
                    Loop
                    digitos(n) += 1
                    For n = n + 1 To 5
                        digitos(n) = digitos(n - 1) + 1
                    Next
                    combina = 0
                    For n = 0 To 5
                        combina += digitos(n) * (10 ^ (5 - n))
                    Next
                Else
                    combina += 1 : digitos(5) += 1
                End If
                k += 1
            Loop While (combina < final)
            s_Combinas(k) = combina
        End Sub

        'Public ReadOnly Property Permuta(ByVal X As UInt16)
        '    Get
        '        Return s_Combinas(X)
        '    End Get
        'End Property
    End Class

    ' Mostras la lista de permutaciones en el listbox.... va en conjunto con la propiedad 'Permuta' de la clase permutaciones.
    'Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    '    Dim k As UInt16, j As UInt32, s As String = ""

    '    ListBox1.Items.Clear()
    '    For k = 0 To Permuta.Cantidad - 1
    '        j = (Permuta.Permuta(k))
    '        If (j < 123456) Then s = "0" & j.ToString Else s = j.ToString
    '        ListBox1.Items.Add(s)
    '    Next
    'End Sub
End Class



Despues los adornos se los pongo jejeje

saludos
Luis



Que tu sabiduria no sea motivo de Humillacion para los demas

Serapis

#14
Cita de: luis456 en  3 Mayo 2021, 08:31 AMen el ejemplo anterior usas los números que pongo de ejemplo  " 2, 3, 5,6,8, 9 " pero estos números cambian después de cada sorteo (después os explicare como los saco)
Que yo ponga ciertos valores de ejemplo, son solo para eso, para ver un ejemplo en marcha. Y puesto a poner un valor de ejemplo, qué mejor que poner los mismos que tu, que se supone que has probado y conoces de la guna manera su resultado, tal que un vistazo te permita descubrir si en efecto hace o no como se espera.
Es lógico que esos números cambien con cada sorteo-ocasión... por eso son variables , si no serían constantes y si fueran constantes, entonces bastaría calcularlos una vez al inicio y no haría falta ningún botón...
Lo que quiere decir... que los cambies por otros cualesquiera que necesites a cada ocasión (dentro de lo que admite)...

Cita de: luis456 en  3 Mayo 2021, 08:31 AM
según voy entiendo el código este toma solo los dos primeros y los combina con el resto ,bien el tema es que como sabemos las decenas son hasta el cuatro y a veces tendría que introducir ejemplo ( 1 , 2 ,4 - 5,7,8 ) y ahora el programa para las combinaciones no toma el cuatro solo el 1 y 2




Código (vbnet) [Seleccionar]

txt = TextBox1.Text.Replace(" ", "")
Nums = txt.Split(",")

Esa linea de código, lo único que hace es eliminar espacios en blanco...
La siguiente línea de código, lo que hace es construir un array con cada elemento que resulte tras una coma...
Si te fijas en tu texto (que he resltado en negrita y de color rojo), entre el 4 y el -5 falta una coma, luego el 'split' fallará en obtener 6 números, ahí obtendrá una cadena de texto que al intentar parsearlo (yo puse byte.parse, no resulta preciso poner byte.Tryparse, cuando uno mismo es quien escribe los datos, no proceden de una fuente desconocida que 'a saber lo que contiene...'). Más aún, puesto que falta una coma, solo se hallarán 5 indices para el array, luego te saldrá un mensaje diciendo que deben ser 6 numeros separados por coma.

Por otro lado (cuando pongas la coma en su sitio), si los dígitos decimales van del 0 al 9, no entiendo por qué pones -5. Recuerda que yo no he puesto más interceptor de errores que distinguir si hay 6 indices en el array. Cada uno de esos valores deben ser 1 solo dígito entre el 0 y el 9, y los dos primeros restringido a un valor entre 0 y 4.
Debes ceñirte al formato que tú mismo especificaste mensajes atrás.




Cita de: luis456 en  3 Mayo 2021, 08:31 AM
' <<<<<<<<<<<<<<   ACA CAMBIAN LOS NUMEROS NUNCA SON LOS MISMOS
'...Y DEBE TOMAR HASTA EL DIGITO 4  SABEMOS QUE LAS DECENAS SON 0 1 2 3 Y 4

Vamos a ver... tu premisa era que los dos primeros dígitos (solo 2), apuntaban al valor de decenas y los otros 4 siguiente (siempre 4), a los valores de las unidades...
Entonces si son solo los dos primeros dígitos, cuál es el problema?. Pueden tomar valores 0-4, pero 'valores', siempre serán solo 2 dígitos... ejemplos:

Dec   Unidades
------------------
0,4,    1,6,2,4
2,3,    1,4,0,9
4,2,    6,8,1,3
Como se ve siempre hay dos conjuntos:
- El de decenas son siempre dos dígitos, cuyos valores pueden variar entre el 0 y el 4.
- El de unidades son siempre 4 dígitos, cuyos valores pueden variar entre el 0 y el 9.
Tienes que separar conceptos... En ninguna parte se ha dicho que las decenas hayan de ser cualesquiera dígitos cuyo valores caiga en el rango 0-4, solo se refiere a los 2 primeros dígitos.

...pues esa fue tu premisa, te cito:
Cita de: luis456 en  1 Mayo 2021, 22:28 PM
yo tengo  6 dígitos  ejemplo  2 3 5 6 8 9 <--- esos números deberán de formar parejas de esta forma :
de este grupo se toma el 2 y 3 solamente y se combinan con el resto :  5 6 8 9
 formando pares de dígitos :


Este código, precisamente tiene por objeto obtener como parámetros ambos valores, fíjate como yo los 'desmonto' en dos parámetros (el 'tutti-fruti' es muy mala idea en programación).
Citar
' crear los parámetros para la funcion de Transformacion:
          ' Los dos dígitos de las 'decenas':
           Decenas(0) = System.Byte.Parse(Nums(0))
           Decenas(1) = System.Byte.Parse(Nums(1))

          ' Los 4 dígitos de las 'unidades':
           For k = 2 To 5
               Unidades(k - 2) = System.Byte.Parse(Nums(k))
           Next
Lo ideal es que cada uno tuviera su propio textbox, y para impedir introducción de datos incorrectamente mejor usar controles específicos, por ejemplo controles 'numericUpDown', que puedes limitar sus valores con sus propiedades minimun y maximun (abajo te pongo un dibujo a mano alzada de como podría ser), aunque dichos controles, no tienen opción de bloquear valores individuales más allá del rango definido por las propiedades antedichas:




Esto suele ser ineficiente... recorrer todos los controles, para vaciar el contenido de 8 o 10 textbox...
Cita de: luis456 en  3 Mayo 2021, 08:31 AM
, he puesto un botón para limpiar y poder hacer pruebas y el código va de maravilla ,pongo el código y algunas observaciones  a ver que te parece ?
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
       For Each obj As Control In Me.Controls
           If (TypeOf obj Is TextBox) Then
               obj.Text = ""
           End If
           If (TypeOf obj Is GroupBox) Then
               For Each caja As Control In obj.Controls
                   If (TypeOf caja Is TextBox) Then
                       caja.Text = ""
                   End If
               Next
           End If
           ListBox1.Items.Clear()


       Next
   End Sub

Es preferible otras alternativas:
Cuando son pocos textbox (pongamos 4-12... uno mismo decide cuando son pocos).
Código (vbnet) [Seleccionar]

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
   Textbox1.text = ""
   OtroTextbox.Text =""
   txtboxNumero.text = ""
   txtBoxCantidad.text=""
   ' ...
end sub


Cuando son una cantidad moderada (>12, por ejemplo)
Se adjunta una variable de tipo coleccion y en New (tras la llamada a InitializeComponent, o incluso mejor en 'InitializeComponent' al final del todo) se introduce cada control que deba ser borrado de una tacada cuando se pulse el botón 'reset'.
Código (vbnet) [Seleccionar]

private ColTxtBox as new collection

private sub New(...)
   call InitializeComponent

   call AddTextBoxToCollection '<--- OJO: No antes de InitializeComponent
end sub

private sub AddTextBoxToCollection
   ColTxtBox.add(Textbox1)
   ColTxtBox.add(OtroTextbox)
   ColTxtBox.add(txtboxNumero)
   ColTxtBox.add(txtBoxCantidad)
   '...
end sub

' Cuando deban ser borrados:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
  dim txtbox as textbox

   for each txtbox in ColTxtBox
       txtbox.text = ""
   next
end sub


Y por último... cuando la cantidad es inmensa y sobretodo si además de borrar el contenido de los textbox hay que restablecer otras propiedades de otros objetos:
Es preferible crear una ventana modal, que contenga toda esa interfaz... cuando se quiera borrar todo, o sea hacer un reset... simplemente se cierra la ventana... como cerrar la ventana no es intuitivo de lo que implica, se añade un botón 'Reset' (y dicho botón lo hace de forma transparente al usuario).

Desde la ventana principal (o una función main, si esa ventana resultase ser toda la interfaz del programa):
- Añade un modulo de código...
- Esto iría en dicho módulo y debe indicarse en las propiedades del proyecto, que la aplicación arranca desde 'Main' (en NET se exige que primero debe añadirse el módulo, si no no estará disponible dicha opción)...
- Para que incluso esa opción esté disponible, antes hay que hacer antes una de dos cosas (como tu caso no es una aplicación de consola, es la opción 'A'):
---- A - Desmarcar: "Habilitar marco de trabajo de la aplicación".
---- B - Marcar que es una 'aplicación de consola'...
Código (vbnet) [Seleccionar]

Module Module1
   Public ResetApp As Boolean

   Public Sub Main()
       Dim frm As Form1

       Do
           ResetApp = False        ' Si no se indica exprofeso, se cierra la app...
           frm = New Form1         ' crea la nueva ventana
           frm.ShowDialog()        ' la carga y hasta que no se cierre, no se ejecutará la siguiente línea de código.
           frm = Nothing           ' elimina el contenido actual
       Loop While (ResetApp = True)
   End Sub
End Module


En la ventana... añadimos un botón y el código asociado a dicho botón será:
Código (vbnet) [Seleccionar]

Public Class Form1
   Private Permuta As New Permutaciones
   Private Decenas(2) As Byte, Unidades(4) As Byte

   Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
       Module1.ResetApp = True
       Me.Close()
   End Sub

   ' ...

Esa línea ("Module1.ResetApp = True"), es para distinguir cuando estás haciendo un 'reset' de cuando la aplicación termina de verdad, para salir del bucle en Main... sin ella será como 'el día de la Marmota' con Bill Murray...

Esto te permite reabrir la ventana cuantas veces quieras, sin necesidad de cerrar y abrir la aplicación y tendrás la interfaz en su estado inicial, ergo un reset, muy 'barato' en código... ya en la carga de la ventana uno se afana en que cada control tenga el valor inicial que deba tener, luego es preferible delegar en ello cuando es complejo y costoso restablecer un estado inicial.




Por último...  
Cita de: luis456 en  3 Mayo 2021, 08:31 AM
 
Código (vbnet) [Seleccionar]

  ...

       Public Sub New()
           Dim combina As UInteger = 12345       ' combinacion inicial -----------NO ENTIENDO ESTO YA QUE LOS NUMEROS DE LAS DECENAS NO PUEDEN PASAR DEL 4
           Dim final As UInteger = 456789           '  combinación final --------------???????????????
Esos son valores que definen el inicio y final del bucle.
Cada dígito, representa sobretodo su posición... '012345' equivale a decir
0 el par de digitos XY
1 el par de dígitos XR
2 el par de dígitos XS
3 el par de dígitos XT
4 el par de dígitos XU
5 el par de dígitos YX
Son 2 dígitos, porque hay que formar 6 números, olvida que sean 012345, igual podría haber elegido letras... ABCDEF, pero tomandolo como números sale más eficiente en ´calculo' y más rentable en memoria (ocupan 2 bytes por indice, frente a un cadena representando 6 caracteres, que serían 6 bytes por indice).

Si 'descomentas' los dos funciones de abajo, añades un botón que referencie al código del botón (aquí se llama button2), y ejecutas el programa y pulsas el botón el listbox se llena con los valores de dicho array... son las 210 combinaciones en 'crudo', son combinaciones abstractas, la función transformar hace un cambio de codificación de los valores de ese array interpretando cada dígito conforme a los dígitos recibidos... es una traducción de código desde uno abstracto y fijo a uno específico, el código para interpretar dicho cambio son los dígitos recibidos.
Código (vbnet) [Seleccionar]
         
      Public ReadOnly Property Permuta(ByVal X As UInt16)
           Get
               Return s_Combinas(X)
           End Get
       End Property
   End Class

   ' Mostras la lista de permutaciones en el listbox.... va en conjunto con la propiedad 'Permuta' de la clase permutaciones.
   Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
       Dim k As UInt16, j As UInt32, s As String = ""

       ListBox1.Items.Clear()
       For k = 0 To Permuta.Cantidad - 1
           j = (Permuta.Permuta(k))
           If (j < 123456) Then s = "0" & j.ToString Else s = j.ToString
           ListBox1.Items.Add(s)
       Next
   End Sub
End Class

Ese array contiene las 210 permutaciones de forma 'condensada' (como la leche), que es más eficiente que recrear desde cero cada vez cada combinación... (la mitad del trabajo, la mitad más 'pesada' se hace una sola vez, durante la creación de la clase).

Que lo entiendas o no, ya depende de tus conocimientos y capacidades... pero te pondré un ejemplo:
Sean los días de la semana: Lunes, martes, miercoles...
Acaso no puede uno ejemplificarlos con números Lunes=1, Martes=2, miercoles= 3... (en programación sería una enumeración)...
Entonces yo luego podría querer almacenar datos en la forma: "el trabajador Luis, esta semana trabajó los días: 1,3,5,6". ...por que en una base de datos (por ejemplo), en ese formato ocupa mucho menos espacio que escribir los nombres de los 4 días en que ha trabajado... pero qué si luego uno quiere tener los días textuales, después de todo, uno no sabe 1 es lunes o es martes o incluso domingo...
...pues resulta que deberá haber una decodificación, un cambio de formato...
Código (vbnet) [Seleccionar]

dim dia as string

dia = DecodificarDia(3)
messagebox.show(dia)

function DecodificarDia(byval D as byte) as string
   Select case D
       case 1: devolver "Lunes"
       case 2: devolver "Martes"
       case 3: devolver "Miércoles"
       case 4: devolver "Jueves"
       case 5: devolver "Viernes"
       case 6: devolver "Sábado"
       case 7: devolver "Domingo"
       case else: devolver "Error, no existe el día: " & d.tostring
   end select
end function

Más aún... ese código, vale incluso si cambias de idioma, variando simplemente los valores constantes que son los nombres de los dias de la semana, bastando para ello un parámetro adicional 'idioma', y que derive a un select case u otro, o simplemente que cargue desde fichero, array, base dedatos, etc... los nombres de los días que corresponden al idioma entrado.
La función Transformar hace esto último, con cada día que se le pide (al caso se le piden todos)...

Ten en cuenta, que cambiar condicionantes en combinatoria, suele suponer tener que tirar todo y rehacerlo de nuevo, por eso antes de empezar, uno debe tener claro y fijo que es lo que pretende hacer. No hay fórmulas universales, tal que una modificación suponga solo cambiar un dato (que a veces pudiera ser, pero por lo general no). Un prisma, un cubo, una esfera... cada uno tiene su fórmula para calcular su volumen... aunque en tal caso si hay una solución universal si 'existe físicamente', pués se sumerge en un líquido y ya Arquímedes y su eureka, solucionaron el caso.

No sé si me dejo algo en el tintero, pero creo que ya queda un mensaje largo... adjunto el dibujo antes que lo olvide:

luis456

UFFFF JAJJAJA

Bueno tendré que imprimir esto y llevármelo al trabajo a ver si asimilo todo y muchas gracias por tu paciencia ,pero te explico estoy haciendo pruebas con varios ejemplos y en una de ellas pongo 2 3 4 6 7 8 y no me salen combinaciones con el cuatro si de terminal estilo 24 34 pero no me salen con el cuatro 42 43 etc etc . y lo de las 210 combinaciones no es limitante se supone que con otro digito saldrán mas combinaciones ,no te preocupes por lo demás que aunque no sea experto ,se como hacer que guarde, imprima libere las variables etc ,

esto lo puse d prisa y corriendo tengo muchos modelos a usar pero me vale para ir viendo como funciona el codigo
Código (vbnet) [Seleccionar]
' FUNCION LIMPIAR LISTBOSX...
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        For Each obj As Control In Me.Controls
            If (TypeOf obj Is TextBox) Then
                obj.Text = ""
            End If
            If (TypeOf obj Is GroupBox) Then
                For Each caja As Control In obj.Controls
                    If (TypeOf caja Is TextBox) Then
                        caja.Text = ""
                    End If
                Next
            End If
            ListBox1.Items.Clear()



Y claro que tomare en cuenta tus métodos pero ya tenia mas de dos años sin programar y lo mío es autodidacta aunque no se crea jejje (eso que estudie Cobol y Pascal ) cuando los Dinosaurios no tenían ni disco duro 😲

es que no se como pasar una toma de pantalla para que veas que es lo que hago,  porque no entiendo si pongo 1 3 4, 6 7 8 no me salen combinaciones con el cuatro adelante ???

13
14
31
34
41
43


Saludos
Luis





















Que tu sabiduria no sea motivo de Humillacion para los demas

Serapis

#16
Cita de: luis456 en  3 Mayo 2021, 13:16 PM
estoy haciendo pruebas con varios ejemplos y en una de ellas pongo 2 3 4 6 7 8 y no me salen combinaciones con el cuatro si de terminal estilo 24 34 pero no me salen con el cuatro 42 43 etc etc .
Esa combinación de dígitos, empieza por 2 y 3, Los dos primeros dígitos de la serie,  son los únicos dígitos que son (pueden ser) decenas, los otros 4 solo pueden ser unidades...
Si el 4 ha de aparecer como decena, deberá intercambiarse por alguno de los dos primeros:
Si tienes 2 3 4 6 7 8 y quieres que el 4 aparezca en las decenas, intercámbialo por ejemplo por el 2:
2 3 - 4 6 7 8
4 3 - 2 6 7 8

Insisito en que fue lo que tú indicaste. Te pedí ejemplos, para en el caso de alguna ambigüedad resolver dudas consultando los ejemplos (a veces puede resultar más fácil terminar de expresar, o acotar lo que alguien quiere poniendo ejemplos)...
Citar
yo tengo  6 dígitos  ejemplo  2 3 5 6 8 9 <--- esos números deberán de formar parejas de esta forma :

de este grupo se toma el 2 y 3 solamente y se combinan con el resto :  5 6 8 9  formando pares de dígitos :
estos son los números resultantes
23  25  26 28 29
32  35  36 38 39
Resultado de esa combinación es esta ...
23,25,26,28,29,32
23,25,26,28,29,35
23,25,26,28,29,36
23,25,26,28,29,38
23,25,26,28,29,39
23,25,26,28,32,35
23,25,26,28,32,36
23,25,26,28,32,38
23,25,26,28,32,39
23,25,26,28,35,36
23,25,26,28,35,38

Si resulta que eso es solo mi interpretación de tu especificación, es que entonces es inexacta, o cuando menos incompleta y exigíria redefinirla con exactitud y rehacerlo todo...

Cita de: luis456 en  3 Mayo 2021, 13:16 PM
y lo de las 210 combinaciones no es limitante se supone que con otro digito saldrán mas combinaciones ,no te preocupes por lo demás que aunque no sea experto ,se como hacer que guarde, imprima libere las variables etc
No. Esas son todas las formas de ordenar los dígitos en las condiciones (actuales) establecidas.
Antes bien, según los dígitos pasados, se formará alguna combinación ilegal... No se filtran porque se da por sentado que uno sabe reconocer que cualquier valor fuera dle rango 01-49 es inválido.


En realidad, a estas alturas asumo que lo que quieres, no encaja con la especificación resuelta.
Podemos hacer un último intento, pero considera entonces que no me pondría con ello mientras no quede todo perfectamente determinado, sin dudas y sin ambigüedades.
Rehacer cosas por emerger requisitos que no se dieron cuando se solicitaron, es algo siempre muy molesto y propenso a ser rechazado (porque implica que todo el tiempo previo empleado es completamente inútil, lo que no ofrece garantías de que ahora no fuera a ser distinto)...
Y hay que poner ejemplos, sobre todos de los casos 'irregulares', porque cuando uno no se expresa bien, puede verse plasmado en los ejemplos cierta intencionalidad...

Considera que el número total de combinaciones de la primitiva eleigiendo 6 número distintos entre el 1 y el 49, viene acotado por la fórmula: (49*48*47*46*45*44) = 10.068.347.520
Con ello quiero indicar que si tu acotación no restringe en cierta medida el número de combinaciones posibles, se puede disparar y resultar impráctico... si al final salen 2 millones de combinaciones (por ejemplo), que aunque sea una minucia respecto de la totalidad, carece de practicidad albergarlas en un listbox y mucho menos recrearlo con cada cambio de uno u otro dígito. Elegir unas pocas combinaciones entre 2 millones, al final no es muy distinto de elegirlas de entre los 10 mil millones...
La quiniela por ejemplo son 3^14 = 4.782.969 de permutaciones totales.


Cita de: luis456 en  3 Mayo 2021, 13:16 PM
es que no se como pasar una toma de pantalla para que veas que es lo que hago,  porque no entiendo si pongo 1 3 4, 6 7 8 no me salen combinaciones con el cuatro adelante ???
Hay una tecla (Impr Pant) suele estar a la dercha de la tecla F12 (segúne el teclado). Eso hace una captura de la pantalla. Se abre un programa de im agen (basta cualquiera por simple que sea, que permita rcortar y guardar a fichero), se pega la imagen (teclas CTRL+V), y se edita... normalmente para recortar el área que es de interés, se copia y pega la selección (del recorte) como nueva imagen. Luego se guarda a fichero como jpg... cuando tiene texto, e spreferible como png, que conserva mejor los detalles de las letras.
Después se localiza el fichero en el disco, y se sube a una página de subida de imágenes (por ejemplo https://www.imgur.com ).
Después de subirla a una página, hay que tomar en enlace (de los que ofrezca elegir uno que ponga 'bbCode para foros'), y se pega el enlace en tu respuesta...
En realidad se tarda más en explicarlo con detalle que en hacerlo.



















luis456

ien Serapis tratare de explicarlo al pelo ya que tienes razon,esta desde el princio mal planteado ,

bueno la idea es poder combinar 6 digitos iniciales que van desde el 0 hasta el 9 (0,1,2,3,4,5,6,7,8,9 ), bien de estos numeros
que yo escojo segun una ecuacion matematica (mia) 6 digitos los cuales yo combino segun la tematica de apuesta
de la primitiva que ya sabemos es hasta el 49, con estos 6 digitos se deben formar los numeros (decenas) que componen el sorteo

ejemplo : introducimos  ( 1, 2, 3, 4, 5, 6 ) con estos numeros se formarian los siguientes numeros:
12 13 14 15 16
21 23 24 25 26
31 32 34 35 36
41 42 43 45 46 <----tomariamos hasta aca los numeros para combinarlos entre si formando grupos de 6
51 52 53 54 56 <----ya estos no se toman en cuenta ( se eliminan del calculo)
61 62 63 64 65 <----ya estos no se toman en cuenta ya que se salen del rango max (49)

Seguimos: del grupo de arriba tomariamos los numeros desde el 12 hasta el 46, ya que como sabemos las loteria llegan hasta el 49 y
habiendo excluido el 51 hasta el 65 nos quedarian desde el 12 hasta el 46 y esos son los numeros que vamos a combinar

vamos a calcular otro ejemplo ( 1,3,4,5,7,9 ) se deben de formar los siguientes numeros

13,14,15,17,19
31,34,35,37,39
41,43,45,47,49
y con estos numeros formar las combinaciones posibles de 6

Muy importante es lo siguiente debe tomar en cuenta cuando se introducen los 6 digitos que los digitos( 0 1 2 3 y 4 ) forman las decenas
y que se deben combinar con el resto de los digitos y entre si para formar lo que ya sabemos es la forma de juego de la loteria
primitiva y bonoloto.

gracias de antemano por tu enorme paciencia :)

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

Serapis

A ver si he entendido bien, y simplificando:

Dados 6 digitos cualquiera que sea el orden en que se den, se trata de obtener con ellos todas las combinaciones posibles legales (agrupadas de 6 en 6, claro).

Así, un dígito podrá ponerse como decena siempre que sea menor de 5, y un digito mayor de 5 solo podrá ponerse como unidad.

Un ejemplo: 7,9,2,1,8,0

01, 12, 17, 18, 19
10, 12, 07, 08, 09
20, 21, 27, 28, 29
...

Es así?

Todavía no me queda claro, si podría ser válido algo como:
01, 11, 22, 27, 28, 29
Es decir se permite que si un dígito es menor de 5, combinarse consigo mismo, o queda restringido a combinarse solamente con los demás?.
Si no se permite el único modo de formar 11, 22, 33 y 44, es que aaprezca 2 veces ese dígito, como en:
3, 2, 5, 7, 2, 6

luis456

Bien la primera parte esta bien, a si mismo es pero en la parte que me comentas que debe aparecer dos veces el mismo digito no podrá ser ya que son números que no se repiten  y además se prestaría a confusión ,si no se puede hacer vamos a dejarlo por ahora (después miramos a hacerlo sin tener que meter dos veces el mismo digito ,por lo demás esta bien a si es como debe funcionar,

Saludos y gracias
Luis



Que tu sabiduria no sea motivo de Humillacion para los demas