Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: goto C en 28 Julio 2013, 13:54 pm



Título: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 13:54 pm
Hola, este es mi primer mensajito jeje, me he visto obligado a pedir ayuda, al principio me veía capaz, pero después de probar mil códigos diferentes y ver que siempre todos fallan en algún punto acudo para pedir que me echéis una mano, plissss.

El caso, tengo un array (correctamente inicalizado y comprobado que contiene bien los caracteres y todo ok), así, suponiendo que contiene los caracteres; a b c d, el programa debe hacer las siguientes combinaciones:

ab
ac
ad
bc
bd
cd
abc
abd
bcd
abcd

Nota: si se conoce el número de caracteres es relativamente sencillo, pero se trata de hacer combinaciones del modo que explico sin saber el número de caracteres, es decir, el usuario introduce por teclado el número, y a continuación los caracteres, pero el código del programa debe estar preparado para funcionar sea cual sea el número, si no me explico me lo decís jeje.

No importa el orden, únicamente importa que estén todas las combinaciones. Me extraña que no haya ningún algoritmo ya desarrollado que haga esto, ¿no tiene ningún nombre realizar combinaciones de esta manera?, pregunto par poder googlear jeje.
Bueno, si a alguien se le ocurre cómo hacerlo, aunque sea la idea, no es necesario que me de el código, se lo agradezco mucho. El programa es en C, aunque si alguno sabe hacerlo en otro lenguaje que lo haga en ese y ya lo "traduciremos" jeje.

Muchísimas gracias. Saludos.


Título: Re: ¿Algoritmo existente?
Publicado por: Stakewinner00 en 28 Julio 2013, 13:59 pm
Si quieres que haga todas las combinaciones de unos caracteres puede buscar por fuerza bruta.
Lo del numero a que te refieres?


Título: Re: ¿Algoritmo existente?
Publicado por: amchacon en 28 Julio 2013, 14:06 pm
Yo ya lo tengo hecho y realizado:

Recursivo:

Código
  1. const char Diccionario[]= {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
  2. 'p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J'
  3. ,'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3',
  4. '4','5','6','7','8','9','\0'};
  5.  
  6. const int Tamanyo_Diccionario;
  7.  
  8. //...
  9.  
  10. Tamanyo_Diccionario = strlen(Diccionario);
  11.  
  12. // Llamamos a la funcion
  13.  
  14. while(!explora(intento,password,0,hasta)) { hasta++;
  15.    intento[hasta] = '\0';}
  16.  
  17. printf("La contrasenaya es: %s",intento);
  18.  
  19. //...
  20.  
  21. char explora (char* Password,const char* Correcta, int desde, int hasta){
  22.  if (desde==hasta){
  23.    return !strcmp(Password,Correcta);
  24.  }else{
  25.    int i = 0;
  26.    for (i=0; i< TamanyoDiccionario; i++){
  27.      Password [desde] = Diccionario[i];
  28.       if (explora (Password, Correcta, desde+1, hasta))
  29.        return 1;
  30.    }
  31.  }
  32.  return 0;
  33. }

Otra modalidad iterativa (lo usé para resolver sudokus y está en C++, tendrás que adaptarlo):

Código
  1. bool Resolver(short Tablero[MAX][MAX])
  2. {
  3.    vector<pair<int,int> > Casillas;
  4.    for (short j = 0; j < MAX;j++)
  5.        for (short i = 0; i < MAX;i++)
  6.            if (Tablero[i][j] == 0)
  7.                Casillas.push_back(make_pair(i,j));
  8.  
  9.    register short Inicio = Casillas.size()-1;
  10.  
  11.    short Actual;
  12.    short i;
  13.  
  14.    for (i = 0; i < Casillas.size();i++)
  15.    {
  16.            Tablero[Casillas[i].first][Casillas[i].second] = i%(MAX)+1;
  17.    }
  18.  
  19.   // Ultimo_Movimiento = 1;
  20.  
  21.    while(true)
  22.    {
  23.        for (i = 1; i < MAX;i++)
  24.        {
  25.  
  26.            Tablero[Casillas[Inicio].first][Casillas[Inicio].second] = i;
  27.  
  28.            if (Resuelto(Tablero))
  29.                return true;
  30.        }
  31.  
  32.        Tablero[Casillas[Inicio].first][Casillas[Inicio].second] = 1;
  33.  
  34.        if (Inicio == 0)
  35.                Inicio++;
  36.        else
  37.        {
  38.            Actual = Inicio-1;
  39.  
  40.            Tablero[Casillas[Actual].first][Casillas[Actual].second] ++;
  41.  
  42.            while (Tablero[Casillas[Actual].first][Casillas[Actual].second] > (MAX))
  43.            {
  44.               Tablero[Casillas[Actual].first][Casillas[Actual].second] = 1;
  45.  
  46.                Actual--;
  47.  
  48.                if (Actual == -1)
  49.                {
  50.                    return false;
  51.                }
  52.                Tablero[Casillas[Actual].first][Casillas[Actual].second]++;
  53.  
  54.            }
  55.  
  56.        }
  57.  
  58.    }
  59.  
  60. }


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 14:54 pm
Gracias a los dos, muchas gracias. Amchacon, te he enviado un mensaje con unos problemillas que tengo con tu programa, si no te importa, cuando tengas tiempo échale un vistacillo que estoy muy perdido jejeje.

Stakewinner00 lo que estoy tratando de hacer es un generador de fuerza bruta, lo que sucede es que ya tengo todas las partes principales del programa funcionando, solamente me falta ésta que os comento, lo cual no es fuerza bruta, pues son solamente algunas combinaciones de todas las posibles con esos caracteres. Aunque si alguno sabe de alguna manera (directamente, sin varias partes de código) de hacer todas las combinaciones posibles (fuerza bruta) de otra manera que lo diga porfa jejeje, que me adapto.

Con lo del número me refiero a que pueden ser 3 caracteres o 15, es decir, lo único en común es la manera de hacer las combinaciones, que es como explico en el ejemplo.

Saludos y gracias. :rolleyes:


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 21:02 pm
Amchacon, he estado mirando tu programa, el que está en C, no el de C++, y me da errores de compilación, ¿qué compilador usas?

Además agradecería que alguien me explicara un poco el código, porque no entiendo bien el funcionamiento ni cómo está estructurado.

Saludos, gracias.


Título: Re: ¿Algoritmo existente?
Publicado por: Stakewinner00 en 28 Julio 2013, 21:08 pm
Amchacon, he estado mirando tu programa, el que está en C, no el de C++, y me da errores de compilación, ¿qué compilador usas?

Además agradecería que alguien me explicara un poco el código, porque no entiendo bien el funcionamiento ni cómo está estructurado.

Saludos, gracias.

El código falta aplicarlo. Tienes que poner los includes necesarios, el main, etc.


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 21:46 pm
Ya hombre, eso ya está hecho, además me lo mandó amchacon completo, pero ni con esas compila...


Título: Re: ¿Algoritmo existente?
Publicado por: Stakewinner00 en 28 Julio 2013, 21:49 pm
Ya hombre, eso ya está hecho, además me lo mandó amchacon completo, pero ni con esas compila...
Postea aquí el código entero y te intentamos ayudar


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 22:17 pm
Código:
#include <stdio.h>
#include <string.h>

const char Diccionario_Default[]= {'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','z','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','Z','0','1','2','3',
'4','5','6','7','8','9','\0'};

const char Diccionario_Mayusculasoff[] = {'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','z','0','1','2','3','4','5','6','7','8','9','\0'};

const char Diccionario_Minusculasoff[] = {'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','Z','0','1','2','3',
'4','5','6','7','8','9','\0'};

const char Diccionaro_Numerosoff[] = {'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','z','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','Z','\0'};

const char Diccionario_MayusculasNumerosoff[]= {'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','z','\0'};

const char Diccionario_MinusculasNumerosoff[]= {'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','Z','\0'};

const char Diccionario_MayusculasMinusculasoff[]= {'0','1','2','3','4','5','6','7','8','9','\0'};

char* Diccionario = Diccionario_Default;
int TamanyoDiccionario = 0;
char explora (char* Password,const char* Correcta, int desde, int hasta);

int main()
{
    char LongitudMin;
    char Opcion;
    char password[256];
    char intento[256] = "as";
    //char* valor = fgets(password,255,stdin);

    TamanyoDiccionario = strlen(Diccionario);
    puts("Introduce tu contrasenya: ");

    scanf("%s",password);

    puts("Quieres proporcionar opciones adicionales? (s/n): ");
    scanf(" %c",&Opcion);

    if (Opcion == 's' || Opcion == 'S')
    {
         char Mayuscula;
        char Minuscula;
        char Numeros;
        puts("Que longitud tiene al menos contrasenya? ");
        scanf("%d",&LongitudMin);

        if (LongitudMin < 0)
            LongitudMin = 0;

        puts("Tiene letras mayusculas? (S/N) ");
        scanf(" %c",&Mayuscula);

        puts("Tiene letras minusculas? (S/N)");
        scanf(" %c",&Minuscula);

        puts("Tiene numeros? (S/N)");
        scanf(" %c",&Numeros);

        #define Afr(tipo) (tipo == 's' || tipo == 'S')

        if (!Afr(Mayuscula) && !Afr(Minuscula) && Afr(Numeros)) // 001
            Diccionario = Diccionario_MayusculasMinusculasoff;

        if (!Afr(Mayuscula) && Afr(Minuscula) && !Afr(Numeros)) // 010
            Diccionario = Diccionario_MayusculasNumerosoff;

        if (!Afr(Mayuscula) && Afr(Minuscula) && Afr(Numeros)) // 011
            Diccionario = Diccionario_Mayusculasoff;

        if (Afr(Mayuscula) && !Afr(Minuscula) && !Afr(Numeros)) // 100
            Diccionario = Diccionario_MinusculasNumerosoff;

        if (Afr(Mayuscula) && !Afr(Minuscula) && Afr(Numeros)) // 101
            Diccionario = Diccionario_Minusculasoff;

        if (Afr(Mayuscula) && Afr(Minuscula) && !Afr(Numeros)) // 110
            Diccionario = Diccionaro_Numerosoff;

        if (Afr(Mayuscula) && Afr(Minuscula) && Afr(Numeros)) // 111
            Diccionario = Diccionario_Default;

        TamanyoDiccionario = strlen(Diccionario);// Generar Diccionario

    }
    else
        {
            LongitudMin = 0;
        }

    int hasta = LongitudMin;

    while(!explora(intento,password,0,hasta)) { hasta++;
    intento[hasta] = '\0';}

    printf("La contrasena es %s",intento);

    return 0;
}

char explora (char* Password,const char* Correcta, int desde, int hasta){
  if (desde==hasta){
    return !strcmp(Password,Correcta);
  }else{
    int i = 0;
    for (i=0; i< TamanyoDiccionario; i++){
      Password [desde] = Diccionario[i];
       if (explora (Password, Correcta, desde+1, hasta))
        return 1;
    }
  }
  return 0;
}


Título: Re: ¿Algoritmo existente?
Publicado por: Stakewinner00 en 28 Julio 2013, 22:18 pm
Pues ami si que me compila todo y que me da alertas podrías poner lo que te pone ati?
Citar
a.c:80:25: warning: assignment discards 'const' qualifier from pointer target ty
pe [enabled by default]
Ahora miro por que se trata, ya editare si eso.

EDITO: El error ocurre por que lo declaras como const

No estaría mejor declarar un array con todas las posibilidades y luego estableces las que el usuario elija?


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 28 Julio 2013, 22:39 pm
error C2143: error de sintaxis : falta ';' delante de 'tipo'

error C2065: 'hasta' : identificador no declarado

error C2065: 'hasta' : identificador no declarado

error C2065: 'hasta' : identificador no declarado

EDITO: he quitado el const, pero da exactamente los mismos errores.

EDITO 2: amchacon, muy chula tu foto, es lo menos que podemos hacer por recordar a un genio al que nunca se le ha reconocido lo suficiente su trabajo y a quien no conoce esta sociedad en que vivimos, pero sí conoce a Steve Jobs, por ejemplo.


Título: Re: ¿Algoritmo existente?
Publicado por: amchacon en 28 Julio 2013, 23:12 pm
error C2143: error de sintaxis : falta ';' delante de 'tipo'

error C2065: 'hasta' : identificador no declarado

error C2065: 'hasta' : identificador no declarado

error C2065: 'hasta' : identificador no declarado

EDITO: he quitado el const, pero da exactamente los mismos errores.
¿Has probado el código literalmente o has hecho algun cambio?

EDITO 2: amchacon, muy chula tu foto, es lo menos que podemos hacer por recordar a un genio al que nunca se le ha reconocido lo suficiente su trabajo y a quien no conoce esta sociedad en que vivimos, pero sí conoce a Steve Jobs, por ejemplo.
;)


Título: Re: ¿Algoritmo existente?
Publicado por: do-while en 29 Julio 2013, 09:57 am
¡Buenas!

Aquí te dejo otro código. Trabaja las combinaciones sobre un vector de enteros, ya que es lo único que te hace falta. Hacer combinaciones sobre un vector de cualquier cosa es hacer combinaciones sobre los indices del vector...

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct t_combinatoria
  6. {
  7.    unsigned long **lista;
  8.    unsigned long n_elementos;
  9.    unsigned long longitud_elemento;
  10. };
  11. typedef struct t_combinatoria t_combinatoria;
  12.  
  13. void inicializar_combinatoria(t_combinatoria *c)
  14. {
  15.    c->lista = NULL;
  16.    c->n_elementos = 0;
  17.    c->longitud_elemento = 0;
  18. }
  19.  
  20. void finalizar_combinatoria(t_combinatoria *c)
  21. {
  22.    unsigned long i;
  23.  
  24.    for(i = 0 ; i < c->n_elementos ; i++)
  25.        free(c->lista[i]);
  26.  
  27.    free(c->lista);
  28.  
  29.    c->lista = NULL;
  30.    c->n_elementos = 0;
  31.    c->longitud_elemento = 0;
  32. }
  33.  
  34. unsigned long factorial(unsigned long n)
  35. {
  36.    unsigned long ret = 1;
  37.  
  38.    while(n)
  39.        ret *= (n--);
  40.  
  41.    return ret;
  42. }
  43.  
  44. unsigned long n_sobre_k(unsigned long n, unsigned long k)
  45. {
  46.    return (factorial(n) / factorial(k)) / factorial(n - k);
  47. }
  48.  
  49. int combinaciones(t_combinatoria *datos,unsigned long elementos_conjunto, unsigned long elementos_combinacion)
  50. {
  51.    static unsigned long indice = 0;
  52.    static unsigned long elementos_fijados = 0;
  53.    static unsigned long *aux = NULL;
  54.    unsigned long i;
  55.  
  56.    if(!elementos_combinacion)
  57.        return 0;
  58.  
  59.    if(indice == elementos_combinacion)
  60.    {
  61.        memcpy(*(datos->lista + elementos_fijados), aux, elementos_combinacion * sizeof(unsigned long));
  62.  
  63.        elementos_fijados++;
  64.  
  65.        return 1;
  66.    }
  67.  
  68.    /* si es la primera vez que llamamos a la funcion, reservamos memoria para la tabla de combinaciones */
  69.    if(!indice)
  70.    {
  71.        if(!(aux = (unsigned long *) malloc(elementos_combinacion * sizeof(unsigned long))))
  72.            return 0;
  73.  
  74.        datos->n_elementos = n_sobre_k(elementos_conjunto,elementos_combinacion);
  75.        datos->longitud_elemento = elementos_combinacion;
  76.  
  77.        if(!(datos->lista = (unsigned long **) malloc(datos->n_elementos * sizeof(unsigned long *))))
  78.        {
  79.            datos->n_elementos = 0;
  80.            datos->longitud_elemento = 0;
  81.  
  82.            return 0;
  83.        }
  84.  
  85.        for(i = 0 ; i < datos->n_elementos ; i++)
  86.        {
  87.            if(!(datos->lista[i] = (unsigned long *) malloc(datos->longitud_elemento * sizeof(unsigned long))))
  88.            {
  89.                int j;
  90.  
  91.                for(j = 0 ; j < i ; j++)
  92.                    free(datos->lista[i]);
  93.  
  94.                free(datos->lista);
  95.                datos->lista = NULL;
  96.  
  97.                datos->n_elementos = 0;
  98.                datos->longitud_elemento = 0;
  99.  
  100.                return 0;
  101.            }
  102.        }
  103.  
  104.        for(i = 0 ; i < elementos_conjunto - elementos_combinacion + indice + 1; i++)
  105.        {
  106.            aux[indice] = i;
  107.  
  108.            indice++;
  109.  
  110.            combinaciones(datos, elementos_conjunto, elementos_combinacion);
  111.  
  112.            indice--;
  113.        }
  114.  
  115.        free(aux);
  116.        aux = NULL;
  117.        elementos_fijados = 0;
  118.        indice = 0;
  119.    }
  120.    else
  121.    {
  122.        for(i = aux[indice - 1] + 1 ; i < elementos_conjunto - elementos_combinacion + indice + 1; i++)
  123.        {
  124.            aux[indice] = i;
  125.  
  126.            indice++;
  127.  
  128.            combinaciones(datos, elementos_conjunto, elementos_combinacion);
  129.  
  130.            indice--;
  131.        }
  132.    }
  133.  
  134.    return 1;
  135. }
  136.  
  137. int main(int argc, char *argv[])
  138. {
  139.    unsigned long i,j,k;
  140.    t_combinatoria comb;
  141.    char *vocales = "aeiou";
  142.  
  143.    for(i = 1 ; i <= 5 ; i++)
  144.    {
  145.        inicializar_combinatoria(&comb);
  146.  
  147.        combinaciones(&comb, 5 , i);
  148.  
  149.        for(j = 0 ; j < comb.n_elementos ; j++)
  150.        {
  151.            for(k = 0 ; k < comb.longitud_elemento ; k++)
  152.                printf("%c",vocales[comb.lista[j][k]]);
  153.            printf("\n");
  154.        }
  155.  
  156.        finalizar_combinatoria(&comb);
  157.    }
  158.  
  159.    return 0;
  160. }
  161.  

Había visto un error que no existia...  :P

¡Saludos!


Título: Re: ¿Algoritmo existente?
Publicado por: goto C en 29 Julio 2013, 17:02 pm
Amchacon, lo he compilado sin modificar absolutamente nada. Do-while, ya sé que lo único que me hace falta es "jugar" con las posiciones de los elementos del array, pero  lo que no encuentro es el cómo combinarlos, es decir, un algoritmo que haga esas combinaciones sea cual sea el número de caracteres, y ahí es donde os pido ayuda.

Os pongo aquí parte del código que es donde tengo los problemas, este código es, de todos los que he probado hasta la fecha, el que mejor funciona posiblemente y el que es más sencillo de comprender porque es el más corto.

Código:
#include<stdio.h> 
#include<stdlib.h>

int main()
{
    int numcarac, auxnumcarac, i, j, k, l=0, contador=1; //numcarac es el numero de caracteres del array carac y auxnumcarac el de caraccomb
    char carac[26], caraccomb[26]; //carac es el array con todos los caracteres, y caraccomb el array en el que iremos guardando las diferentes combinaciones de los caracteres de carac

//... pedimos datos por teclado, los guardamos y los mostramos para asegurarnos, esto funciona bien, comprobado, no lo pongo para no liar mas

//AQUI ESTA EL PROBLEMA:
auxnumcarac=2;

   for(i=0; i<numcarac; i++)
   {
      for(j=i; j<numcarac; j++)
      {
         for(k=0; k<auxnumcarac; k++)
         {
            caraccomb[l] = carac[j+k];
            l++;
         }

         //aqui mostramos caraccomb:
         printf("%s\n", caraccomb);

      }
      auxnumcarac++;
      l=0;
   }

Gracias y saludos. :D
A ver si podéis orientarme un poco en el código este.