Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: snake_linux en 5 Septiembre 2015, 14:33 pm



Título: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 14:33 pm
Hola a tod@s, esta mañana he intentado crear en C un generador de diccionario, en plan que tu le dices de 5 caracteres y en teoría debería de ir desde "aaaaa" hasta "zzzzz" pero me ha sido un infierno, he probado de todo, he concatenado 3 fors que fueran desplazando la posicion he hecho de todo y no lo he conseguido, no quiero que me deis el código para ver como se hace (no me gusta que me den el trabajo hecho, y tampoco estaría bien pediros eso), solo quiero saber si realmente, es tan dificil o si realmente soy malo programando por que es que me ha frustado muchísimo.

Hice algo así en batch cuando tenía 15 años pero eran un montón de for anidados y digamos que el método no era muy "elegante" pero funcionar funcionaba, el caso es que ahora que "en teoría" se C me habría gustado conseguirlo, pero es que me he tirado horas delante del PC y solo he conseguido pillarme un cabreo.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: tincopasan en 5 Septiembre 2015, 15:08 pm
Si no entendí mal, lo que estás buscando, es hacer combinaciones, que se usa en matemáticas, empezá buscando sobre desarrollo de combinaciones y permutaciones.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: xiruko en 5 Septiembre 2015, 15:18 pm
Hola a tod@s, esta mañana he intentado crear en C un generador de diccionario, en plan que tu le dices de 5 caracteres y en teoría debería de ir desde "aaaaa" hasta "zzzzz" pero me ha sido un infierno, he probado de todo, he concatenado 3 fors que fueran desplazando la posicion he hecho de todo y no lo he conseguido, no quiero que me deis el código para ver como se hace (no me gusta que me den el trabajo hecho, y tampoco estaría bien pediros eso), solo quiero saber si realmente, es tan dificil o si realmente soy malo programando por que es que me ha frustado muchísimo.

Bueno, ese programa que pides es algo bastante simple... No diré que eres malo programando, sino simplemente que aun estás muy verde y necesitas practicar mucho.

Saludos, y no te desanimes!


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 16:27 pm
He encontrado este código en internet:

Código
  1. #include <stdio.h>
  2.  
  3. #include <stdlib.h>
  4.  
  5. #include <string.h>
  6.  
  7.  
  8.  
  9. int main(int argc, char *argv[])
  10.  
  11. {       if(argc < 2 || !strcmp(argv[1], "-h")) //Texto de ayuda
  12.  
  13.        {
  14.  
  15.                puts("HELP: \nsintax: dic [len_dic] (optional)[list]");
  16.  
  17.                return 1;
  18.  
  19.        }
  20.  
  21.  
  22.  
  23.        int len=0, cont=atoi(argv[1]), *cad, i, ver=1; //Declaracion
  24.  
  25.        cad=(int *)malloc(sizeof(int) * atoi(argv[1])); //Reserva de memoria para un array int
  26.  
  27.        memset((int *)cad,0,sizeof(int) * atoi(argv[1]));//Inicializamos el array a 0
  28.  
  29.        char *lst;//Declaracion de la lista que contendra las posibilidades
  30.  
  31.  
  32.  
  33.        if(argc < 3) //Comprobamos el numero de parametros introducidos para hacer una cosa u otra
  34.  
  35.        {
  36.  
  37.                lst=(char *)malloc(strlen("abcdefghijklmnopqrstuvwxyz")+1);
  38.  
  39.                strcpy(lst, "abcdefghijklmnopqrstuvwxyz");
  40.  
  41.        }
  42.  
  43.        else if(argc == 3)
  44.  
  45.        {
  46.  
  47.  
  48.  
  49.                        lst=(char *)malloc(strlen(argv[2])+1);
  50.  
  51.                        if(!lst)
  52.  
  53.                        {
  54.  
  55.                                puts("No se pudo reservar la memoria");
  56.  
  57.                                return 1;
  58.  
  59.                        }
  60.  
  61.                        strcpy(lst, argv[2]);
  62.  
  63.        }
  64.  
  65.  
  66.  
  67.        while(len+1<=cont)//Comienza el ciclo de generacion
  68.  
  69.        {
  70.  
  71.                if(lst[cad[0]]!='\0')
  72.  
  73.                {
  74.  
  75.                        for(i=0;i<=len;i++)
  76.  
  77.                        {
  78.  
  79.                                putchar(lst[cad[i]]);                  
  80.  
  81.                        }
  82.  
  83.                        putchar('\n');
  84.  
  85.                }
  86.  
  87.                if(lst[cad[0]]!='\0')
  88.  
  89.                {
  90.  
  91.                        cad[0]++;
  92.  
  93.                }
  94.  
  95.                else
  96.  
  97.                {
  98.  
  99.            ver=0;
  100.  
  101.                        for(i=0;i<=len;i++)
  102.  
  103.                        {
  104.  
  105.                                if(lst[cad[i]]=='\0')
  106.  
  107.                                {
  108.  
  109.                                        cad[i]=0;
  110.  
  111.                                        cad[i+1]++;
  112.  
  113.                                }
  114.  
  115.                                else
  116.  
  117.                                {
  118.  
  119.                                        ver=1;
  120.  
  121.                                }
  122.  
  123.                        }
  124.  
  125.                }
  126.  
  127.                if(ver==0)
  128.  
  129.                {
  130.  
  131.                        len++;
  132.  
  133.                        for(i=0;i<=len;i++)
  134.  
  135.                        {
  136.  
  137.                                cad[i]=0;
  138.  
  139.                        }
  140.  
  141.                        ver=1;
  142.  
  143.                }
  144.  
  145.        }
  146.  
  147.        free(lst);
  148.  
  149.        free(cad);
  150.  
  151.        return 0;
  152.  
  153. }

Funciona a la perfección y se ve muy simple, pero sinceramente aunque me guste la programación creo que novoy a valer para esto, por que este código ya digo, tiene pinta de ser muy simple, pero me hago un lio y no entiendo nada.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: T. Collins en 5 Septiembre 2015, 17:28 pm
Hay que tener bastante experiencia para leer código de otra persona, al principio no es fácil, no te rindas a la primera. Intenta simplificar los problemas para no frustrarte.

En vez de intentar con 5 caracteres empieza con 2, por ejemplo, y un diccionario más pequeño:

Código:
diccionario = "abcdef";
for(x=0;x<strlen(diccionario);x++)
{
       for(i=0;i<strlen(diccionario);i++)
       {
               print diccionario[x], diccionario[i];
       }
}


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 17:54 pm
Hay que tener bastante experiencia para leer código de otra persona, al principio no es fácil, no te rindas a la primera. Intenta simplificar los problemas para no frustrarte.

En vez de intentar con 5 caracteres empieza con 2, por ejemplo, y un diccionario más pequeño:

Código:
diccionario = "abcdef";
for(x=0;x<strlen(diccionario);x++)
{
       for(i=0;i<strlen(diccionario);i++)
       {
               print diccionario[x], diccionario[i];
       }
}


Ese método es el que yo usé hace años en batch, y funciona bien, el problema está en que quiero que sea modular, es decir, quiero poder elegir el número de caracteres, además el problema de ese método es que para por ejemplo 10 caracteres necesitas 10 fors anidados.

Gracias por tus animos, me he frustado mucho y llevo un mal dia.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 18:03 pm
El código se quedaría así, es una chorrada yo lo quería hacer mucho más elegante:

Código
  1. #include <stdio.h>
  2.  
  3. #include <stdlib.h>
  4.  
  5. #include <string.h>
  6.  
  7.  
  8.  
  9. int main(int argc, char *argv[]) {
  10.  
  11.    char caracteres[]="abcdefghijklmnopqrstuvwxyz";
  12.  
  13.    int x, y;
  14.  
  15.    for(x=0;x<strlen(caracteres);x++) {
  16.  
  17.        for(y=0;y<strlen(caracteres);y++) {
  18.  
  19.            printf("%c%c\n", caracteres[x], caracteres[y]);
  20.  
  21.  
  22.  
  23.  
  24.        }
  25.  
  26.  
  27.  
  28.  
  29.    }
  30.  
  31.  
  32.  
  33.  
  34. }

PD: ¿ Alguien me explica un método más elegante y sobretodo, más reutilizable donde pueda elegir el número de caracteres, o por lo menos, explicarme el código de arriba que he puesto ?.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: someRandomCode en 5 Septiembre 2015, 19:44 pm
Te doy una idea y te mejoro el concepto:
Se llama generar permutaciones de un grupo.
Dado un grupo A = { 'a','b','c' } todas las permutaciones de dos valores con repeticion, no hace falta hacer tres bucles.
Te paso un pedacito de codigo que me robe de stackoverflow porque no estoy encasa:
Código
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. unsigned powu(unsigned base, unsigned exp){
  6.    unsigned result = 1;
  7.    while(exp > 0){
  8.        if(exp & 1)
  9.            result *= base;
  10.        base = base * base;
  11.        exp >>=1;
  12.    }
  13.    return result;
  14. }
  15.  
  16. int main(int argc, char *argv[]){
  17.    if(argc != 3){
  18.        fprintf(stderr, "Usage : RepeatedPermutation abcd 3\n");
  19.        return -1;
  20.    }
  21.    char *list = argv[1];
  22.    unsigned gp_len = atoi(argv[2]);
  23.    unsigned list_len = strlen(list);
  24.    char *gp = calloc(gp_len+1, sizeof(char));
  25.    int total_n = powu(list_len, gp_len);
  26.    int i, j;
  27.    for(i=0;i<total_n;++i){
  28.        int n = i;
  29.        for(j=0;j<gp_len;++j){
  30.            gp[gp_len -j -1] = list[n % list_len];
  31.            n /= list_len;
  32.        }
  33.        printf("[%s]\n", gp);
  34.    }
  35.    free(gp);
  36.    return 0;
  37. }
  38.  

No hace falta que te lo comente, pero si necesitas explicacion de algo me decis..


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: RockPosts en 5 Septiembre 2015, 20:16 pm
Para dejar mi miga de pan, os dejo un simple ejemplo de como generar el diccionario y a su vez guardarlo en un archivo:

Código
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstdio>
  4. #include <cmath>
  5.  
  6. int main() {
  7. FILE * lpstFilePointer = NULL;
  8. char lpszFilePath[256];
  9. char *lpString = NULL;
  10. int nNumCharacters = 0;
  11.  
  12. std::cout << "Cuantos caracteres necesitas? ";
  13. std::cin >> nNumCharacters;
  14.  
  15. std::cout << "Donde deseas guardar los datos? ";
  16. std::cin >> lpszFilePath;
  17.  
  18. lpstFilePointer = fopen((const char *)lpszFilePath, "w");
  19.  
  20. if(lpstFilePointer == NULL) {
  21. std::cout << "Error al abrir el archivo en la ruta '" << lpszFilePath << "'. El programa se va a cerrar";
  22. std::cin.get();
  23. return 1;
  24. }
  25.  
  26. lpString = new char[nNumCharacters];
  27.  
  28. if(lpString == NULL) {
  29. std::cout << "Error al declarar la cadena temporal para generar el diccionario.";
  30. std::cin.get();
  31. return 1;
  32. }
  33.  
  34. for(int i = 0; i <= (int)pow(26, nNumCharacters); i++) {
  35. itoa(i, lpString, 26);
  36.  
  37. for(int e = 0; e < nNumCharacters; e++) {
  38. if(lpString[e] != 0) {
  39. if(lpString[e] <= 57)
  40. lpString[e] += 49;
  41. else
  42. lpString[e] += 10;
  43. }
  44. }
  45.  
  46. fputs(lpString, lpstFilePointer);
  47. fputc('\n', lpstFilePointer);
  48. }
  49.  
  50. std::cout << "El programa ha finalizado el proceso.";
  51. fclose(lpstFilePointer);
  52. std::cin.get();
  53. return 0;
  54. }


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 22:52 pm
Te doy una idea y te mejoro el concepto:
Se llama generar permutaciones de un grupo.
Dado un grupo A = { 'a','b','c' } todas las permutaciones de dos valores con repeticion, no hace falta hacer tres bucles.
Te paso un pedacito de codigo que me robe de stackoverflow porque no estoy encasa:
Código
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. unsigned powu(unsigned base, unsigned exp){
  6.    unsigned result = 1;
  7.    while(exp > 0){
  8.        if(exp & 1)
  9.            result *= base;
  10.        base = base * base;
  11.        exp >>=1;
  12.    }
  13.    return result;
  14. }
  15.  
  16. int main(int argc, char *argv[]){
  17.    if(argc != 3){
  18.        fprintf(stderr, "Usage : RepeatedPermutation abcd 3\n");
  19.        return -1;
  20.    }
  21.    char *list = argv[1];
  22.    unsigned gp_len = atoi(argv[2]);
  23.    unsigned list_len = strlen(list);
  24.    char *gp = calloc(gp_len+1, sizeof(char));
  25.    int total_n = powu(list_len, gp_len);
  26.    int i, j;
  27.    for(i=0;i<total_n;++i){
  28.        int n = i;
  29.        for(j=0;j<gp_len;++j){
  30.            gp[gp_len -j -1] = list[n % list_len];
  31.            n /= list_len;
  32.        }
  33.        printf("[%s]\n", gp);
  34.    }
  35.    free(gp);
  36.    return 0;
  37. }
  38.  

No hace falta que te lo comente, pero si necesitas explicacion de algo me decis..

Muchas gracias, me ha servido de mucho, solo unos cuantos detalles:

- Para que sirven los operadores ">>" y el operador "&" (este último lo había visto pero solo como "&&")
- Me gustaría que, si no es mucho pedir, me explicaras o me pasaras algún enlace que explique, el algoritmo (la fórmula) para las permutaciones con repetición de grupo ( que es lo que me has dicho ), lo he estado buscando yo por mi cuenta, pero solo encuentro con números y no se como aplicarlo a esto (leo el código pero si no se la fórmula "original" me cuesta un poco leerlo, aunque es bastante claro)

Saludos y gracias por la ayuda.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: someRandomCode en 5 Septiembre 2015, 22:59 pm
La verdad que http://www.vitutor.com/pro/1/a_6.html (http://www.vitutor.com/pro/1/a_6.html) es todo lo que necesite para entenderlo..
Pero al caso, << es para para correr el numero binario tantos como son necesarios hacia el lado que indica el simbolo, o sea, >> es su operacion contraria.
Si estuvieramos en C++ esto significaria el desplazamiento de flujo que funciona distinto dependiendo del tipo/clase

En cuanto al algoritmo de generacion, la parte mas complicada es la de seleccionar la posicion a la cual incrementar al siguiente elemento del grupo..

Fijate si con la lectura que te pase lo entendes sino te lo comento..


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 5 Septiembre 2015, 23:36 pm
La verdad que http://www.vitutor.com/pro/1/a_6.html (http://www.vitutor.com/pro/1/a_6.html) es todo lo que necesite para entenderlo..
Pero al caso, << es para para correr el numero binario tantos como son necesarios hacia el lado que indica el simbolo, o sea, >> es su operacion contraria.
Si estuvieramos en C++ esto significaria el desplazamiento de flujo que funciona distinto dependiendo del tipo/clase

En cuanto al algoritmo de generacion, la parte mas complicada es la de seleccionar la posicion a la cual incrementar al siguiente elemento del grupo..

Fijate si con la lectura que te pase lo entendes sino te lo comento..

Gracias por ayudarme :)

La lectura que me has pasado, pone una fórmula para calcular el número de posibilidades, pero aún no se como haces para "calcular" cada posibilidad, así que si puedes comentármelo mejor.

PD: ¿ Y para que sirve "&" en vez de "&&" ?.

Saludos.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: RockPosts en 5 Septiembre 2015, 23:44 pm
Citar
Para que sirven los operadores ">>" y el operador "&" (este último lo había visto pero solo como "&&")

*El operador >> sirve para lo que se denomina 'Desplazamiento de Bits' Esto sirve para lo que su nombre dice. Me explico con un ejemplo: tenemos una variable de tipo entero (int) cuyo valor es 12. Dicho numero en binario es 1100. Si hacemos la siguiente operación...
Código
  1. varialbe = variable >> 1
entonces estamos desplazando todos los bits un lugar, dando como resultado el numero en binario 0110. El 1 que estaba en cuarto lugar ha pasado al tercer lugar. El 1 que estaba en tercer lugar ha pasado al segundo lugar... y así sucesivamente. Si hubiéramos hecho esto...
Código
  1. variable = variable >> 2
entonces daría como resultado 0011 en binario

*El operador & es parecido al |. Lo que hace es multiplicar bit a bit dos valores. Por ejemplo, tenemos los valores 011010 y 110011 (en binario). Si hacemos 011010 & 110011 obtendremos 010010.
Empezamos de derecha a izquierda: El primer bit está determinado por la operación 1 * 0, por lo que vale 0. El segundo bit está determinado por la operación 1 * 1, por lo que vale 1 y así sucesivamente


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 6 Septiembre 2015, 11:45 am
*El operador >> sirve para lo que se denomina 'Desplazamiento de Bits' Esto sirve para lo que su nombre dice. Me explico con un ejemplo: tenemos una variable de tipo entero (int) cuyo valor es 12. Dicho numero en binario es 1100. Si hacemos la siguiente operación...
Código
  1. varialbe = variable >> 1
entonces estamos desplazando todos los bits un lugar, dando como resultado el numero en binario 0110. El 1 que estaba en cuarto lugar ha pasado al tercer lugar. El 1 que estaba en tercer lugar ha pasado al segundo lugar... y así sucesivamente. Si hubiéramos hecho esto...
Código
  1. variable = variable >> 2
entonces daría como resultado 0011 en binario

*El operador & es parecido al |. Lo que hace es multiplicar bit a bit dos valores. Por ejemplo, tenemos los valores 011010 y 110011 (en binario). Si hacemos 011010 & 110011 obtendremos 010010.
Empezamos de derecha a izquierda: El primer bit está determinado por la operación 1 * 0, por lo que vale 0. El segundo bit está determinado por la operación 1 * 1, por lo que vale 1 y así sucesivamente

Gracias, me ha servido de ayuda.


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: someRandomCode en 6 Septiembre 2015, 14:40 pm
Bien, he regresado xD
Vengo a explicarte por que se usa asi el tema de la posicion:
Examinemos el codigo si?
Lo primero que hacemos es guardar el valor de i, que es el indicador del numero de combinacion general en la que estamos.
Luego entrmos en el for que hace las combinaciones.
El orden se determina por
Código
  1.            gp[gp_len -j -1] = list[n % list_len];
  2.            n /= list_len;
  3.  

gp -> grupo, gp_len -> largo del grupo, j-> posicion actual en el grupo, -1 porque el indice esta basado en ceros
list es la lista de elementos permutables en el grupo.
Entonces:
para cada elemento de gp le en la posicion donde estamos en el bucle (-1) se da el valor del elemento del grupo en relacion al largo del grupo de elementos intercambiables en el round actual (round = valor de i), luego se ajusta n con el largo del grupo deseado.

Esto es asi dado que cada permutacion tiene asociado un numero, si "0000" es 0, "0001" es 1, y "AAAA" es X

No se explicarme muy bien, tendria que agarrar latex y escribirte la formula algebraica de generacion de permutaciones.

Basicamente es que tenes un grupo vacio de universo hasta X elementos.
De tal manera que vas a seleccionar dependiendo del numero un elemento Y para meterlo y puede ser biyectiva(es decir tener dos valores iguales dentro del grupo X partiendo del mismo elemento en Y)


Título: Re: ¿ Tan dificil es hacer un generador de diccionario ?
Publicado por: snake_linux en 6 Septiembre 2015, 23:25 pm
Vale, creo que ya lo he entendido, el problema para mi no es C, es más bien el algoritmo matemático ya que tampoco es que sepa yo muchas mates pero bueno lo que es el código lo entiendo.

Muhas gracias por tu tiempo :)