Ejercicio básico de combinaciones

<< < (2/8) > >>

Serapis:
No estoy seguro de haberte entendido al final... me confunde esto de:
Citar

...en este caso serian 12 números a combinar formando combinaciones de 6 que cumplan la condición...

Tal que lo que yo creí haberte entendido de tu primer mensaje es que partiendo de una lista de 6 números,  tu quieres 'desplazar' esa combinación a las que permita el rango al que quede restringido manteniendo la distancia entre los valores de la serie de entrada...

Bien... si es eso lo que pides, entonces el fallo es que la serie de entrada que ofreces, es una arbitraria... no la distancia absoluta al número. La solución es simple, se trata de desplazar la serie entrada (a la serie absoluta)...

Más simplemente explicado... Si tu quieres poner números en la forma:
5,8,12,13,14,15
Eso debe llevarse a un desplazamiento absoluto es decir: resta 4 a cada uno de ellos ...introduce por tanto:
1,4,8,9,10,11

(En el listado de combinaciones), la primera combinación debe empezar siempre por 1 y la última debe acabar siempre en 49-valormayor. Por tanto la lista de valores deben contener la distancia de los valores respecto de un punto absoluto (preferible a una distancia relativa con anterior o posterior), siendo el primero el valor más bajo (el 1), así cada valor es una distancia absoluta, que sirve de suma y simplifica toda la operatoria del programa.

Si no quieres hacer el cálculo manualmente (para eso existe la programación). Añade otro textbox y otro boton, cuando quieras escribirlos libremente usa ese textbox. Cuando pulses el botón asociado, buscará el 'valor de resta', que se consigue buscando el menor de la lista y restándole 1 (en el ejemplo previo: valorResta = 5-1), ahora en un bucle se resta dicho valor a cada uno de los términos y deposita en resultado en el otro textbox, e invoca el botón del otro textbox...

Te adjunto el código del nuevo botón (no olvides añadir encima un botón y un textbox, fíjate en la imagen que adjunto más abajo).
Código
' Desplazar una serie arbitraria a la serie absoluta e invocar el otro botón.
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
       Dim Nums() As String, txt As String
       Dim Valores() As Byte, k As UInt16, j As Uint16 = 255
 
       txt = TextBox2.Text.Replace(" ", "")
       Nums = txt.Split(",")
       If (Nums.Length = 6) Then
           ' Buscar el menor:
           ReDim Valores(0 To 5)
           For k = 0 To 5
               Valores(k) = System.Byte.Parse(Nums(k))
               If (Valores(k) < j) Then j = Valores(k)
           Next
           ' Hacer la resta:
           j -= 1
           txt = ""
           For k = 0 To 5
               Valores(k) -= j
               txt = (txt & Valores(k).tostring & ", ")
           Next
 
           ' ahora el textbox1 contiene la serie absoluta (canónica) y por tanto se puede invocar el botón con opera con dicha serie.
           TextBox1.Text = txt.Substring(0, txt.Length - 2)  ' no queremos pasar la última coma.
 
           ' Llamamos directamente el botón-1
           Call Button1_Click(sender, e)
       Else
           MessageBox.Show("No, no no... Debe haber 6 y solo 6 numeros, separados por 1 coma...")
       End If
   End Sub
 



(cambio color de letra que se confunde con el texto capturado en la imagen)
Si resulta que no es lo que quieres es que no he terminado de entenderte, redefine tu problema si puedes con 2 o 3 ejemplos específicos completos, de modo que la claridad de la especificación se manifieste en el ejemplo, o bien que donde fallen tus palabras pueda deducirse del ejemplo...

Serapis:
p.d.: Añado una imagen que clarifique el objetivo que creo entender que es el cometido del programa.

- Puede verse (en blanco) la lista de valores elegibles: 1-49...
- La linea roja son valores (de ejemplo) de tu elección.
Dicha línea (en mi supuesto de lo creo haberte entendido), quieres desplazarla hacia uno u otro lado. Así si la desplazas 5 posiciones a la izquierda, los valores resultantes, serían aquellos que están justo encima de los que contiene la 'linea roja'.
- La línea amarilla, representa el límite de la serie más a la izquierda. Esta es en realidad la línea con la que el programa espera trabajar (ahora se ha añadido un nuevo botón y textbox, para  redactar  la linea roja y convertirla en la amarilla).
- La linea de color cyan, representa (para la serie actual), la combinación resultante más a la derecha que se puede alcanzar (manteniendo la distancia entre valores).

K-YreX:
Yo creo que se está complicando demasiado el problema inicial. Y que bastaría con lo que expuse en su momento.

Cita de: K-YreX en 25 Abril 2021, 12:28 pm

Yo diría que algo así te puede servir:
Código
int numeroMaximo = 49;
int[] digitos = { 1, 4, 5, 7, 8, 9 };
List<int> numerosGenerados = new List<int>();
 
int decenaMaxima = numeroMaximo / 10;
int unidadMaxima = numeroMaximo % 10;
 
for(int i = 0; i < digitos.Length && digitos[i] <= decenaMaxima; ++i)
 for(int j = 0; j < digitos.Length && (digitos[i] < decenaMaxima || digitos[j] <= unidadMaxima); ++j)
   numerosGenerados.Add(digitos[i] * 10 + digitos[j]);
** Para que el algoritmo anterior funcione correctamente el array de dígitos debe estar ordenado.
Las condiciones de los bucles for() no son muy complicadas pero cualquier duda no dudes en comentarla.


Salida:
Código:

11 - 14 - 15 - 17 - 18 - 19
41 - 44 - 45 - 47 - 48 - 49

Entrada 2:
Código
int[] digitos = {2, 3, 5, 7, 8, 9};

Salida 2:
Código:

22 - 23 - 25 - 27 - 28 - 29
32 - 33 - 35 - 37 - 38 - 39

Las únicas diferencias que veo son:
[x] El código expuesto está en C# -> Habría que convertirlo a VB.
[x] Aparece también la combinación de un dígito consigo mismo. Esto se corrige así:
Código
for(int i = 0; i <digitos.Length && digitos[i] <= decenaMaxima; ++i)
 for(int j = 0; j < digitos.Length && (digitos[i] < decenaMaxima || digitos[j] <= unidadMaxima); ++j)
   if(i != j) numerosGenerados.Add(digitos[i] * 10 + digitos[j]);

Serapis:
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...


Remplazar el método del mismo nombre por éste y listo.
Código
Private Sub Combinaciones(ByVal Valores As Byte())
       Dim j, k, max, min As Byte
       Dim combinacion As String = ""
 
       ListBox1.Items.Clear()
 
 
       min = (Valores.Min - 1)                     ' Comienzo
       max = (49 + min - Valores.Max)
       For j = 0 To max
           For k = 0 To 5
               combinacion &= ((Valores(k) + j - min).ToString) & ", "
           Next                                            ' Fin
 
           ListBox1.Items.Add(combinacion)
           combinacion = ""
       Next
   End Sub
 
Tiene 2 bucles igual que tu solución, probablemente más sencilos de entender, la concatenaicón de ítems para añadirlo a un listbox tampoco es nada complejo.

El resto de código que queda fuera de las líneas con los comentarios 'comienzo y 'fin, es simplemente manejo de la interfaz.

luis456:
Voy a tratar de explicarlo (siempre me pasa lo mismo yo se lo que quiero pero no se explicarlo)

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 (no las pongo todas son bastantes )

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

Como ven solo no salen combinaciones con el cuatro ni el uno ni cero ya que no salen en los números para combinar ( 2 3 5 6 8 9 )

saludos
Luis

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

[*] Página Anterior