Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: javirk en 31 Enero 2012, 21:26 pm



Título: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 31 Enero 2012, 21:26 pm
Hola, pues me gustaría hacer un programa que al que tú le dijeras 3 números y lo que tienen que dar las cuentas entre ellos y que te diera los signos, del tipo:
Números:
7
2
1

Resultado:
8

Y que el programa te dijera: 7+2-1=8

O algo parecido. Había pensando en poner Ifs con todas las condicionales, pero son muchas y no me parece lo más adecuado, ¿se os ocurre alguna otra forma?

El programa lo estoy haciendo en C++, por eso lo pongo aquí.

Un saludo y gracias


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 3 Febrero 2012, 20:09 pm
Ok, he encontrado que se puede hacer con "backtracking", pero no sé cómo funciona eso, y eso que he leído bastante al respecto...


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: eleon en 3 Febrero 2012, 21:28 pm
Podrías explicarte mejor por favor, ¿estás diciendo que el usuario introduce los operandos y las operaciones que quieres que haga con ellos (como una calculadora)?.

No está permitido hacer los ejercicios, sin embargo si te explicas bien se te puede orientar acerca de por dónde tirar.


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: raul338 en 3 Febrero 2012, 21:51 pm
Bactracking ya es avanzado de por si, se podria decir que es una inteligencia aplicada :P

Lo que si puedes hacer es el tipico "fuerza bruta", o sea, con un for ir cambiando todo tipo, sumar, restar y asi

1º Vuelta
Suma 1º
Suma 2º
Suma 3º

Es correcto? No? Entonces cambio el primero por una resta
2º Vuelta
Suma 1º
Resta 2º
Suma 3º

y asi con todas las operaciones, claro, tarda mas exponecialmente segun los numeros que haya, pero seria la forma mas "simple" de hacerlo :P


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 4 Febrero 2012, 14:04 pm
Podrías explicarte mejor por favor, ¿estás diciendo que el usuario introduce los operandos y las operaciones que quieres que haga con ellos (como una calculadora)?.

No está permitido hacer los ejercicios, sin embargo si te explicas bien se te puede orientar acerca de por dónde tirar.

El usuario sólo introduce los números, el programa da los signos.

@raul338 No entiendo cómo podría hacer eso con un for...

Muchas gracias por la ayuda!


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: ghastlyX en 4 Febrero 2012, 14:27 pm
Si la cantidad de números puede ser arbitraria, tienes que hacer un backtracking. Si la cantidad de números es fija, puedes simular el backtracking a base de bucles. En todo caso, si tienes n números, la complejidad resultante es O(2n).

Puedes también hacer una dinámica, si los números y el resultado están acotados será mucho más eficiente.


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: Xandrete en 4 Febrero 2012, 15:00 pm
¿División también? ¿Producto también?

En realidad, el ejercicio tiene un poco más de "cosa" si admites la división como posible operador, porque has de tener cuidado con no dividir nada entre 0.

Hay otro detalle: el de la jerarquía de las operaciones. Tanto si admites el producto como la división, has de tener en consideración que cualquiera de estas dos operaciones tiene prioridad frente a la suma y la resta.

Si no estabas considerando ni el producto ni la multiplicación, no hay ningún problema.

Coincido con las personas que han comentado que para este caso viene un poco grande el backtracking (no vale la pena aplicarlo para decidir tan solo dos operadores). Para este caso, bastaría con dos bucles for anidados. Inténtalo, es bastante fácil. Si aún así no te sale, arroja algo de código y así te ayudamos un poco más.


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: do-while en 4 Febrero 2012, 17:41 pm
¡Buenas!

Esto me suena al cifras y letras que hubo en tiempos en el foro libre en tiempos.

El programa no es dificil utilizando al goritmos recursivos (si, hice trampas... XD)

Aqui te dejo el codigo que hice, si no entiendes algo avisa. En este caso he utilizado un vector estatico con MAX_CIFRAS elementos. txtresultado tambien tiene fijado el numero de caracteres (el codigo lo hice un poco al vuelo). Si quieres que tu programa funciones bien tendras que corregir esos detalles utilizando memoria dinamica, ya que pueden se fuente de errores.

Tendras que darle una dimension "grande" a txtresultado si quieres asegurarte de que no te pasas del final del bloque...

Código
  1. /*
  2.  * si se puede resolver devuelve 1, sino 0
  3.  *
  4.  * guarda en txtresultado las operaciones que se van realizando para llegar al resultado
  5.  */
  6. int resolver(int *cifras,int ncifras,int resultado,char *txtresultado)
  7. {
  8.    int i,j,operador1,operador2;
  9.  
  10.    /* si el numero de datos restantes es <= 1, no se pueden realizar operaciones */
  11.    if(ncifras <= 1)
  12.        return 0; /* devolvemos falso */
  13.  
  14.    /* emparejamos los numeros de 2 en 2 */
  15.    for(i=0 ; i < ncifras ; i++)
  16.    {
  17.        for(j=0 ; j < ncifras ; j++)
  18.        {
  19.            operador1 = cifras[i];
  20.            operador2 = cifras[j];
  21.  
  22.            if(i!=j) /* un numero no puede operar consigo mismo */
  23.            {
  24.                if(i < j) /*suma y producto son conmutativas y se realizan solo con i<j */
  25.                {
  26.                    /*
  27.                      * operamos y guardamos la operacion en la cadena que contiene el texto con
  28.                      * el resultado
  29.                      */
  30.                    operacion(cifras,i,j,'+',txtresultado);
  31.  
  32.                    /* si tras la operacion hemos hallada el resultado */
  33.                    if(cifras[i] == resultado)
  34.                        return 1; /* devolvemos verdadero */
  35.  
  36.                    /* en este punto, no se ha hallado ninguna solucion
  37.                      * por lo tanto, buscamos un resultado, con los datos restantes
  38.                      */
  39.                    if(resolver(cifras,ncifras-1,resultado,txtresultado + strlen(txtresultado)))
  40.                        return 1; /* si lo solucionamos, devolvemos verdadero */
  41.  
  42.                    /* si no lo solucionamos, resauramos los valores de los parametros */
  43.                    restaurar(cifras,i,j,operador1,operador2,txtresultado);
  44.  
  45.                    /* y pasamos a la siguiente operacion */
  46.                    operacion(cifras,i,j,'*',txtresultado);
  47.  
  48.                    if(cifras[i] == resultado)
  49.                        return 1;
  50.  
  51.                    if(resolver(cifras,ncifras-1,resultado,txtresultado + strlen(txtresultado)))
  52.                        return 1;
  53.  
  54.                    restaurar(cifras,i,j,operador1,operador2,txtresultado);
  55.                }
  56.  
  57.                //resta y division no conmutativas, asi que las realizamos con todos los pares
  58.  
  59.                operacion(cifras,i,j,'-',txtresultado);
  60.  
  61.                if(i < j)
  62.                {
  63.                    if(cifras[i] == resultado)
  64.                        return 1;
  65.                }
  66.                else
  67.                    if(cifras[j] == resultado)
  68.                        return 1;
  69.  
  70.                if(resolver(cifras,ncifras-1,resultado,txtresultado + strlen(txtresultado)))
  71.                    return 1;
  72.  
  73.  
  74.                restaurar(cifras,i,j,operador1,operador2,txtresultado);
  75.  
  76.                operacion(cifras,i,j,'/',txtresultado);
  77.  
  78.                if(i < j)
  79.                {
  80.                    if(cifras[i] == resultado)
  81.                        return 1;
  82.                }
  83.                else
  84.                    if(cifras[j] == resultado)
  85.                        return 1;
  86.  
  87.                if(resolver(cifras,ncifras-1,resultado,txtresultado + strlen(txtresultado)))
  88.                    return 1;
  89.  
  90.                restaurar(cifras,i,j,operador1,operador2,txtresultado);
  91.            }
  92.        }
  93.    }
  94.  
  95.    return 0;
  96. }
  97.  
  98. void restaurar(int *cifras,int i,int j,int operador1,int operador2, char *txtresultado)
  99. {
  100.    /* movemos los datos a partir del indice mayor una posicion a la derecha */
  101.    if(i < j)
  102.        memmove(cifras + j + 1, cifras + j, sizeof(int) * (MAX_NUMEROS - j - 1));
  103.    else
  104.        memmove(cifras + i + 1, cifras + i, sizeof(int) * (MAX_NUMEROS - i - 1));
  105.  
  106.    /* restauramos los valores originales que habia en el vector */
  107.    cifras[i] = operador1;
  108.    cifras[j] = operador2;
  109.  
  110.    /* y eliminamos la informacion de la operacion de la cadena con la solucion */
  111.    *txtresultado = '\0';
  112.  
  113.    return;
  114. }
  115.  
  116. void operacion(int *cifras,int i,int j,char op,char *txtresultado)
  117. {
  118.    /* guardamos en min{i,j} el bresultado de la operacion */
  119.  
  120.    switch(op)
  121.    {
  122.        case '+':
  123.            sprintf(txtresultado,"%d + %d = %d\n",cifras[i],cifras[j],cifras[i]+cifras[j]);
  124.            cifras[i] += cifras[j];
  125.            break;
  126.  
  127.        case '*':
  128.            sprintf(txtresultado,"%d * %d = %d\n",cifras[i],cifras[j],cifras[i]*cifras[j]);
  129.            cifras[i] *= cifras[j];
  130.            break;
  131.  
  132.        case '-':
  133.            sprintf(txtresultado,"%d - %d = %d\n",cifras[i],cifras[j],cifras[i]-cifras[j]);
  134.  
  135.            if(i < j)
  136.                cifras[i] -= cifras[j];
  137.            else
  138.                cifras[j] -= cifras[i];
  139.  
  140.            break;
  141.  
  142.        case '/':
  143.            if(cifras[j])
  144.                if(!(cifras[i] % cifras[j]))
  145.                {
  146.                    sprintf(txtresultado,"%d / %d = %d\n",cifras[i],cifras[j],cifras[i]/cifras[j]);
  147.  
  148.                    if(i < j)
  149.                        cifras[i] /= cifras[j];
  150.                    else
  151.                        cifras[j] /= cifras[i];
  152.                }
  153.            break;
  154.    }
  155.  
  156.    /* y ahora desplazamos todos los valores a la derecha de max{i,j} una posicion a la izquierda */
  157.  
  158.    if(i < j)
  159.        memmove(cifras + j,cifras + j + 1, sizeof(int) * (MAX_NUMEROS - j - 1));
  160.    else
  161.        memmove(cifras + i,cifras + i + 1, sizeof(int) * (MAX_NUMEROS - i - 1));
  162.  
  163.    return;
  164. }
  165.  

Si encontrais errores o cambiais algo el codigo me gustaria poder echarle un ojo.

¡Saludos!


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: ghastlyX en 5 Febrero 2012, 00:25 am
Antes no había leído que eran tres números. Ignora pues la parte de mi mensaje anterior donde hacía referencia a la solución para una cantidad arbitraria de números. Ya que tu problema es más sencillo, te dejo un código que he picado ahora para el caso general, suponiendo que los operadores son + o -, por si te interesa el tema para mirarlo.
Código
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4.  
  5. void imprime(vector<int>& v, int x) {
  6.    for (int i = 0; i < v.size(); ++i) {
  7.        if ((x >> i)&1) cout << "+";
  8.        else cout << "-";
  9.        cout << v[i];
  10.    }
  11.    cout << endl;
  12. }
  13.  
  14. int main() {
  15.    //Cantidad de numeros, resultado
  16.    int n, m;
  17.    cin >> n >> m;
  18.  
  19.    //Lectura de los numeros
  20.    vector<int> v(n);
  21.    for (int i = 0; i < n; ++i) cin >> v[i];
  22.  
  23.    //Solucion
  24.    for (int i = 0; i < (1 << n); ++i) {
  25.        int res = 0;
  26.        for (int j = 0; j < n; ++j) {
  27.            if ((i >> j)&1) res += v[j];
  28.            else res -= v[j];
  29.        }
  30.        if (res == m) imprime(v, i);
  31.    }
  32. }

Es equivalente a una solución por backtracking, sólo que lo he hecho iterativo mediante máscaras de bits puesto que es mucho más corto y simple el código.


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: Xandrete en 5 Febrero 2012, 02:19 am
Bueno, ya que hay gente que ha puesto su código, me voy a animar yo también... Como ghastlyX ya lo hizo con bucles for anidados, voy a plantear una propuesta distinta.

Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main() {
  5. char comb[][2] = {{'-','-'},{'-','+'},{'+','-'},{'+','+'}};
  6. int a,b,c,result;
  7. cin >> a >> b >> c >> result;
  8. for (int i = 0; i < 4; ++i) {
  9. int res;
  10. if (comb[i][0] == '-') res = a - b;
  11. else res = a + b;
  12. if (comb[i][1] == '-') res -= c;
  13. else res += c;
  14. if (res == result) cout << a << comb[i][0] << b << comb[i][1]
  15. << c << "=" << result << endl;
  16. }
  17. }

Saludos


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 5 Febrero 2012, 16:46 pm
Hola, muchas gracias por vuestras respuestas, de verdad.

do-while, creo que tu solución se me queda algo grande, no sé ni por dónde empezar, pero muchas gracias, lo tendré que mirar más en detalle.

ghastlyX, aún no sé nada de vectores, pero parece que los entiendo más o menos al ver tu solución, muchas gracias.

Xandrete, creo que tu solución es la que más me interesa, posiblemente por ser la más corta, pero no me funciona cuando la compilo, es decir,  que no me sale nada, y meto 4 números y sale del programa; lo mismo me pasa con la de ghastlyX, pero este no sale, simplemente no hace nada. ¿Por qué puede ser eso?

Bueno, a lo que iba, Xandrete, lo que no entiendo del tuyo es eso del "comb[][2]", ¿por qué dos corchetes?

Un saludo y gracias a todos.


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: Xandrete en 6 Febrero 2012, 00:30 am
Hola, muchas gracias por vuestras respuestas, de verdad.

do-while, creo que tu solución se me queda algo grande, no sé ni por dónde empezar, pero muchas gracias, lo tendré que mirar más en detalle.

ghastlyX, aún no sé nada de vectores, pero parece que los entiendo más o menos al ver tu solución, muchas gracias.

Xandrete, creo que tu solución es la que más me interesa, posiblemente por ser la más corta, pero no me funciona cuando la compilo, es decir,  que no me sale nada, y meto 4 números y sale del programa; lo mismo me pasa con la de ghastlyX, pero este no sale, simplemente no hace nada. ¿Por qué puede ser eso?

Bueno, a lo que iba, Xandrete, lo que no entiendo del tuyo es eso del "comb[][2]", ¿por qué dos corchetes?

Un saludo y gracias a todos.

¿Quizás sea porque no existe ninguna combinación de operadores que haga que se cumpla la igualdad? No he tenido ningún problema con el código que te he propuesto. Yo lo he compilado con las opciones -Wall, -Werror y -Wextra para asegurarme de que no había ni error ni warnings de ninguna clase (siempre compilo así) y lo he probado con la entrada que das como ejemplo y con otras.

Con 7 2 1 8 la salida es:

7+2-1=8

Con 0 0 0 0 la salida es:

0-0-0=0
0+0-0=0
0-0+0=0
0+0+0=0

Con 1 1 1 1 la salida es

1+1-1=1
1-1+1=1

Y con 0 0 0 1 no se imprime nada (como ha de ser).

¿Por qué dos corchetes? Porque es un array de arrays de caracteres. O sea, una matriz o estructura de datos bidimensional. Se suelen declarar así, con un par de corchetes. Mírate bien el tema de los arrays.

Otra manera. Con if's, tal y como habías pensado tú al principio:

Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main() {
  5. int a,b,c,result;
  6. cin >> a >> b >> c >> result;
  7. if (a-b-c == result)
  8. cout << a << "-" << b << "-" << c << "=" << result << endl;
  9. if (a-b+c == result)
  10. cout << a << "-" << b << "+" << c << "=" << result << endl;
  11. if (a+b-c == result)
  12. cout << a << "+" << b << "-" << c << "=" << result << endl;
  13. if (a+b+c == result)
  14. cout << a << "+" << b << "+" << c << "=" << result << endl;
  15. }

Este último código si que es claro a más no poder. De todas formas, no nos has sacado de dudas aún acerca del número de signos que consideras. ¿Están la multiplicación y la división también incluidos? Todos estamos asumiendo que sólo te interesan sumas y restas.

Saludos





Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: ghastlyX en 6 Febrero 2012, 01:18 am
Si no te hace nada mi programa y no termina es porque no le pasarás correctamente la entrada. Si te fijas en lo que he dicho o en el código, verás que mi programa no trabaja con tres números, sino con los que tú quieras, lo he hecho para el caso general . El formato de la entrada es primero la cantidad de números que usarás (en tu caso sería 3), a continuación el resultado que buscas y luego los números que se deban usar (tantos como hayas indicado). Por ejemplo, para tu ejemplo sería:
Código:
3 8                                                                                                                                           
7 2 1

Y la salida que produce es
Código:
+7+2-1

Otro caso por ejemplo sería
Código:
5 8
7 2 1 1 1

Y su salida es
Código:
+7+2+1-1-1
+7+2-1+1-1
+7+2-1-1+1


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: do-while en 6 Febrero 2012, 01:39 am
¡Buenas!

No se si el problema esta bien planteado. ¿Los numero hay que utilizarlos en el orden en el que se introducen, o se pueden reordenar?

Lo digo porque si se pueden reordenar, en principipo tendras 4 formas de poner los simbolos de suma y resta en los dos huecos que tienes, y 6 (3!) formas de reorganizar los tres numeros para buscar el resultado, en total 24 casos (que luego se quedan en menos, ya que la suma es conmutativa). Si estas en este ultimo caso, introducir todas las condiciones a mano es largo y bastante propenso a cometer errores...

¡Saludos!

Editado:

Si lo miras con mas detenimiento, solo tienes que variar los coeficientes de los elementos. +/-a, +/-b y +/-c y luego sumarlos, asi queda mas claro, ya que solo tendras que comprobar 8 casos y te olvidas de reordenar los elementos:

a+b+c
a+b-c
a-b+c
-a+b+c
a-b-c
-a+b-c
-a-b+c
-a-b-c


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: Xandrete en 6 Febrero 2012, 09:14 am
¿Reordenar? Bueno, javirk no nos había planteado esa posibilidad.

Si fuera posible, lo que haría simplemente sería considerar un signo más (un - o + antes de la a) y me ahorraría reordenar, que es justo lo que propone do-while. En ese caso habría 23= 8 casos, tal y como nos sugiere. De todas formas, yo apuesto por la Navaja de Ockham y creo que el problema es la versión más sencilla de la que hemos planteado por aquí: sólo dos operadores (suma y resta) y sin posibilidad de reordenación. Y si no es así, que javirk nos dé el enunciado completo de su problema. No tiene sentido que especulemos mientras él no nos dice ni mu xD (javirk, no te mosquees, lo digo sin intención de ofender, a lo mejor no has podido responder aún por alguna razón >.<)

¡Saludos!


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 6 Febrero 2012, 15:56 pm
No he podido jaja estaba en el colegio. El problema no tiene enunciado, me lo he planteado a mí mismo y no se me ocurría forma de hacerlo y por eso pregunté, gracias a todos, de verdad. Lo de la reordenación, pues yo creo que sería como dice Xandrete, en vez de poner al primero el signo positivo, que pueda cambiar entre positivo y negativo.

Y en cuanto a la multiplicación y la división... mejor las dejo de lado, que ahí habría que tener en cuenta demasiadas cosas y no creo que supiera...


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: javirk en 9 Febrero 2012, 22:10 pm
Hola, he estado pensando todos estos días para hacer lo de poner delante del primer número un + o - y así evitar lo del orden, se necesitaría hacer una matriz tridimensional, ¿no?

Otra cosa, Xandrete, no entiendo en tu código por qué cuando
Código:
comb[i][0]=='-'
entonces res=a-b.

Muchas gracias.



Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: Xandrete en 10 Febrero 2012, 01:10 am
A ver. Respondiendo a tu primera pregunta. No, seguiría siendo bidimensional. Sería una matriz 8x3, porque habría 8 casos en total (23) y 3 operadores a decidir.

En el código que te puse (antes del de los if's) la matriz comb es 4x2 porque hay 4 casos en total (22)) y 2 operadores a decidir. El nombre, de hecho, se lo puse por la palabra combinaciones. El sentido de esa matriz es guardar todos los casos posibles: que el primer signo sea - y el segundo -, el primero - y el segundo +, etc.

En cualquier caso, esta solución de la matriz sólo tiene gracia cuando hay poquitos casos. Con 8 casos se me antojaría ya una forma poco elegante y me pasaría a la solución con bucles anidados que te han dado ya con anterioridad.

Tu segunda pregunta. El elemento comb[ i ][0] representa al primer operador de la i-ésima combinación, y comb[ i ][1] al segundo. Si comb[ i ][0] = '-' entonces en res guardamos a - b, y si no, a + b. Luego, a res le sumamos o le restamos c en función de comb[ i ][1]. Comparamos res con result y si son iguales, imprimimos la combinación.

Saludos


Título: Re: Programa que sepa los signos que hay que poner en una igualdad
Publicado por: do-while en 10 Febrero 2012, 04:33 am
¡Buenas!

No te hace falta una matriz. Con tres bucles tienes de sobra:

Código
  1.  
  2. for(i = 0 ; i < 2 ; i++)
  3. {
  4.    for(j = 0 ; j < 2 ; j++)
  5.    {
  6.        for(k = 0 ; k < 2 ; k++)
  7.        {
  8.            (1 - (i * 2)) * a + (1 - (j * 2)) * b + (1 - (k * 2)) * c
  9.            // ...
  10.        }
  11.    }
  12. }
  13.  
  14.  

¡Saludos!