Duda acerca del calculo de combinaciones de numeros y letras en vb.net 2010

Iniciado por arturoro, 14 Noviembre 2015, 07:10 AM

0 Miembros y 1 Visitante están viendo este tema.

arturoro

Hola a todos y buenas noches o dias:

Estuve leyendo acerca del Programa para hacer combinaciones de numeros, y vi que el usuario pkj, hizo y modifico un programa en vb 6.0, y lo puse en vb.net 2010, en donde podias poner el tamaño del grupo y la lista de numeros que querias formar, yo quiero calcular y grabar en un archivo todas las combinaciones de 8 grupos de 2, ya sea numero, letras o la combinacion, por ejemplo el grupo de 8 seria: "AA,BB,CC,15,EE,20,GG,01" y calcular todas las varibles que pueden salir, segun en el propio programa, el total de variables son 40320, y yo deseo grabar todas esas variables, claro, sin repetir.

Al momento de ejecutar el programa con las variables ya descritas, solo hace el primer calculo o mejor dicho, coge las primeras variables, hasta ahi, todo bien, pero, ya no hace los otros calculo, solo saca la primera linea y termina, estuve observando y si muevo el total de la matriz donde guarda los datos obtenidos, me manda error en la matriz de los numeros.

Les paso el link en donde el usuario PKJ (agradezco su valiosa aportacion, ya que es lo que deseo) pone su programa, esta en vb 6.0:

https://foro.elhacker.net/programacion_visual_basic/programa_para_hacer_combinaciones_de_numeros-t414603.10.html

Yo le hice pequeñas modificaciones, les paso el programa para que me puedan orientar o en su defecto ayudar, esta en vb.net 2010

Código (vbnet) [Seleccionar]
Public Class Form1
   Public TamGrupos As Integer = 8 ' Tamaño de los grupos
   Public ListaDeNumeros As String = "AA,BB,CC,DD,EE,FF,GG,HH" ' lista de numeros separados por comas
   Public Parar As Integer

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Parar = 1
   End Sub
   Private Function CalculaTotal(ByVal TamGrupos As Integer, ByVal MaximoValor As Integer) As Long
       Dim C1 As Double
       Dim C2 As Double
       Dim F As Double

       C1 = 1
       C2 = 1
       For F = 1 To TamGrupos
           C1 = C1 * F
       Next F

       For F = MaximoValor To (MaximoValor - (TamGrupos - 1)) Step -1
           C2 = C2 * F
       Next F
       CalculaTotal = C2 / C1

   End Function


   Private Sub CreaGrupos(ByVal TamGrupos As Integer, ByVal TopeOListaDeNumerosSeparadosPorComas As String, ByRef ListaDevuelta() As String)
       ' Busqueda de combinaciones.
       ' Dados los numeros de TopeOListaDeNumerosSeparadosPorComas,
       ' saca todos los grupos no repetidos de "TamGrupos" numeros
       ' y los devuelve en la matriz Lista()
       ' Por repetido se entiende que "1,2,3" es igual que "1,3,2", igual que "2,1,3", etc...
       ' Ejm: 1,2,3,4 de 2 en 2 = 6 combinaciones
       ' 1,2 - 1,3 - 1,4 - 2,3 - 2,4 - 3,4
       ' Opcionalmente, en lugar de una lista de números puedes poner un solo número.
       ' En ese caso la listadenumeros seran los números desde el 1 hasta el que pongas.

       Dim F As Double
       Dim Linea As String
       Dim Num As Double
       Dim Total As Double
       Dim Ap() As Double
       Dim MaximoValor As Long

       Dim MatrizDeNumeros() As String
       MatrizDeNumeros = Split(TopeOListaDeNumerosSeparadosPorComas, ",")
       MaximoValor = UBound(MatrizDeNumeros) + 1

       If MaximoValor = 1 And Val(MatrizDeNumeros(0)) > 0 Then
           MaximoValor = Val(MatrizDeNumeros(0))
           ReDim MatrizDeNumeros(MaximoValor - 1)
           For F = 1 To MaximoValor
               MatrizDeNumeros(F - 1) = F
           Next F
       End If

       Total = CalculaTotal(TamGrupos, MaximoValor)

       ReDim Ap(TamGrupos)

       ReDim ListaDevuelta(Total - 1)
       Dim Contador As Long
       Contador = -1

       Parar = 0

       ' Cogemos las primeras
       For F = 1 To TamGrupos
           Ap(F) = F
       Next F

OtraVez:
       'Preparo la linea con la combinacion
       Linea = ""
       For F = 1 To TamGrupos - 1
           Linea = Linea & MatrizDeNumeros(Ap(F) - 1) & " , "
       Next F
       Linea = Linea & MatrizDeNumeros(Ap(TamGrupos) - 1)

       ' Guardo la combiancion
       Contador = Contador + 1
       ListaDevuelta(Contador) = Linea

       'Label4.Caption = Contador + 1 ' Muestro el progreso

       Application.DoEvents()
       If Parar = 1 Then GoTo Fin

       Num = TamGrupos + 1

Repetir1:
       Num = Num - 1  ' Cogemos la apuesta(num) (en principio la ultima)

       'La aumentamos...
       Ap(Num) = Ap(Num) + 1

       ' si es mayor de la cuenta...
       If Ap(Num) > (MaximoValor - (TamGrupos - Num)) Then

           ' si es la ap(1) se acaba
           If Num = 1 Then GoTo Fin

           ' ...aumentamos la anterior
           GoTo Repetir1
       End If

       ' Si no llega a su limite se mira si alguna ha llegado
       ' a su maximo
       ' Si NUM no apunta a la ultima AP() es que
       ' alguna ap() ha llegado a su maximo
       ' entonces reiniciamos todas las siguientes...
       If Num <> TamGrupos Then
           For F = Num + 1 To TamGrupos
               '....dandoles el valor de la anterior + 1...
               Ap(F) = Ap(F - 1) + 1
           Next F
       End If

       ' ... Y se da por valida
       GoTo OtraVez

Fin:
       Parar = 1

   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

       If Parar = 0 Then Parar = 1 : Exit Sub

       Dim Matriz() As String = Nothing ' matriz donde recibiremos la lista

       CreaGrupos(TamGrupos, ListaDeNumeros, Matriz)

       'Aqui manipulas la matriz como quieras
       ' por ejemplo pasandola a un listbox

       ListBox1.Visible = False
       Dim F As Long
       For F = 0 To UBound(Matriz)
           ListBox1.Items.Add(Matriz(F))
       Next F
       ListBox1.Visible = True

   End Sub
End Class


De antemano Muchas GRACIAS!!!  ;-)

pkj

Hola Arturoro.
No tengo muy claro lo que explicas ni como te ha salido el numero 40320.
Las combinaciones sin repetición de 8 elementos en grupos de 2 creo que serian algo como 7+6+5+4+3+2+1
En tu ejemplo:
7
AA,BB
AA,CC
AA,15
AA,EE
AA,20
AA,GG
AA,01
6
BB,CC
BB,15
BB,EE
BB,20
BB,GG
BB,01
5
CC,15
CC,EE
CC,20
CC,GG
CC,01
4
15,EE
15,20
15,GG
15,01
3
EE,20
EE,GG
EE,01
2
20,GG
20,01
1
GG,01

El problema que veo es que pones grupos de 8 donde deberias poner un 2
Public TamGrupos As Integer = 8 ' Tamaño de los grupos
De modo que solo te muestra 1 grupo con los 8 elementos

Saludos




arturoro

Hola PKJ y gracias por responder   ;-) :

Si, creo que no me explique bien, tu programa esta excelente, solo deseo que los 8 grupos con elementos de 2, haga las combinaciones, y debe de salir mas o menos asi:

GRUPO DE 8 CON 2 ELEMENTOS CADA UNO: AA,BB,CC,8E,Z1,X1,Y0,01     :rolleyes:

Las combinaciones serian mas o menos as1:

AA,BB,CC,8E,Z1,X1,Y0,01
BB,AA,CC,8E,Z1,X1,Y0,01
01,BB,AA,CC,8E,Z1,X1,Y0
CC,8E,Z1,X1,Y0,01,BB,AA

... Y asi sucesivamente hasta que ya no existan mas combinaciones, ya sea poner un listbox, o un archivo.

Gracias por todo y perdona mi ignorancia

SALUDOS!!!  :laugh:

pkj

Entonces no es mi funcion lo que necesitas.

No se me ocurría por donde pillarlo, asi que he usado una sub recursiva muy chula que nos dejó seba123neo, con algunas modificaciones.

Aquí está la sub original:
http://foro.elhacker.net/programacion_vb/combinaciones_vb-t240009.0.html

Y esto es lo que he sacado:

Hace falta un command button y un listbox.

Código (vb) [Seleccionar]
Option Explicit
Private Sub Command1_Click()
  Dim F As Long
  Dim F2 As Long
  Dim Matriz1() As String
  Dim Matriz2() As String
  Dim MatrizFinal() As String
  Dim Linea As String
  Dim Contador As Long
  Dim ListaElementos As String
 
  List1.Clear
 
  ListaElementos = "AA,BB,CC,15,EE,20,GG,01" ' max. 10 elementos

  Matriz1 = Split(ListaElementos, ",") 'separamos los elementos
  For F = 0 To UBound(Matriz1) ' creamos una linea con X numeros
    Linea = Linea & CStr(F)
  Next F
 
  ReDim Matriz2(0)
  Call Combinaciones(Linea, Matriz2) ' creamos la matriz con las combinaciones de los X numeros
 
  ReDim MatrizFinal(0)
  For F = 0 To UBound(Matriz2) - 1
    Linea = ""
    For F2 = 1 To UBound(Matriz1) + 1 ' reemplazamos los numeros por los elementos de la lista
      Linea = Linea & Matriz1(Val(Mid$(Matriz2(F), F2, 1))) & ","
    Next F2
    ReDim Preserve MatrizFinal(Contador)
    MatrizFinal(Contador) = Left(Linea, Len(Linea) - 1) 'guardamos quitando la ultima coma
    Contador = Contador + 1
  Next F
 
  ' mostramos el resultado
  MsgBox "Total " & Contador & " grupos" ' mostramos la cantidad de grupos extraidos
  For F = 0 To UBound(MatrizFinal)
    List1.AddItem MatrizFinal(F) ' y los cargamos en el listbox
  Next F
 
 
End Sub

Private Sub Combinaciones(Palabra As String, ByRef Matriz() As String, Optional strFixed As String)

    Dim i As Integer

    If Len(Palabra) > 1 Then

        For i = 1 To Len(Palabra)

            Combinaciones Left$(Palabra, i - 1) & Mid$(Palabra, i + 1), Matriz, strFixed & Mid$(Palabra, i, 1)

        Next i

    Else
        Matriz(UBound(Matriz)) = strFixed & Palabra
        ReDim Preserve Matriz(UBound(Matriz) + 1)

    End If

End Sub


A la sub de seba123neo solo le he añadido una matriz donde ir dejando los grupos que luego convertiremos segun nuestra necesidad.
Es mejor usar matrices porque un listbox tiene más limitaciones de capacidad.

Espero que te sirva.
Saludos

arturoro

Gracias PKJ, es exactamente lo que necesito  ;-)  , esta en vb 6.0, lo voy a convertir (jejeje!! si eso aplica) a vb.net 2010, y lo voy a subir, y tambien y como una pequeña aportacion y un gran gracias a PKJ, les pongo otro calculo de combinaciones en vb.net 2010, por si alguien le interesa y le saca provecho.

Solo necesitan 2 textbox, 1 listbox y 1 boton.

Código (vbnet) [Seleccionar]
Public Class Form1

   Sub Permutaciones(ByVal a() As String, ByVal j As Integer, ByVal k As Integer, ByVal lista As ListBox)
       Dim i As Integer
       Dim s As String = ""
       Dim sTemp As String
       If j = 1 Then
           For i = 1 To k
               s = s & a(i)
           Next i
           lista.Items.Add(s)
       Else
           For i = 1 To j
               sTemp = a(i)
               a(i) = a(j)
               a(j) = sTemp
               Permutaciones(a, j - 1, k, lista)
               sTemp = a(j)
               a(j) = a(i)
               a(i) = sTemp
           Next i
       End If
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       lbResultados.Items.Clear()
       If txtVariables.Text.Trim.Length >= 2 Then
           Dim x As Integer
           Dim i As Integer
           Dim a() As String
           x = Len(txtVariables.Text)
           ReDim a(x)
           For i = 1 To Len(txtVariables.Text)
               a(i) = Mid(txtVariables.Text, i, 1)
           Next i
           Permutaciones(a, x, x, lbResultados)
           txtTotal.Text = lbResultados.Items.Count.ToString
       Else
           MsgBox("Introduzca un cadena valida")
       End If
   End Sub
End Class


GRACIAS POR TODO!!!   ;-) :rolleyes: ;-) :rolleyes:

Eleкtro

Lo siento, llego tarde al tema (es lo que sucede si publicas en la sección incorrecta).

Ya lo has solucionado de una manera, pero si por casualidad lees esto quiero preguntarte si el rendimiento es un factor importante para tu algoritmo, ya que en caso afirmativo entonces estás desaprovechando todo el potencial que .Net nos ofrece.

Para cálculos de complejidad computacional cómo son las permutaciones y combinaciones, puedes utilizar el paralelismo para ganar una elevada velocidad de procesamiento al utilizar todos los nucleos disponibles, y evitar todos esos wrappers de Vb6 que utilizaste reemplazándolos por el uso de LINQ (o al menos utilizar un For pero con los métodos de manipulación de string equivalentes y el método Array.Copy en lugar de ReDim), ganando así velocidad, mucho más estabilidad del algoritmo y reducción/legibilidad del código, a costa de perder una cantidad ínfima de rendimiento que ya habrías ganado al reemplazar el código vb6-estilizado.

Si lo necesitas dímelo y desarrollo una solución, pero trata de explicame mostrando un ejemplo con las expectativas del resultado de ejecución, ya que no me ha quedado del todo claro que quieres hacer con esos ocho grupos, como quieres calcular las permutaciones;
¿quieres intercambiar las posiciones de cada grupo preservando los 2 caracteres de cada grupo?, ¿o quieres sustituir de forma incrementativa cada caracter de cada grupo?.

Saludos!