Cita de: K-YreX en 2 Mayo 2021, 14:28 PMOk... creí que te referías al código.
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.
Cita de: K-YreX en 2 Mayo 2021, 14:28 PMSí. 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.
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.
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
