Ejercicio 5, práctico 6

Ejercicio 5, práctico 6

de Romina Belen Garcia Camargo -
Número de respuestas: 8

Hola,

En el ejercicio se pide una función que sume dos números cuyos dígitos son elementos de dos listas (los números tienen la misma cantidad de dígitos), y que represente la suma como una lista también (de forma que [1, 4] = 14, [1, 7] = 17, y [1, 4]+[1, 7]= [3, 1]). 

Estuve un rato pensando como resolverlo. Sé que tiene que ser una solución recursiva porque lo pide la letra, y el caso base sería sumar los dos elementos finales (los del lugar de la unidad), y colocar el resto de la división entera de dicho número entre 10 en el primer lugar de la lista resultado, para que los siguientes dígitos se agreguen al principio de la misma. Sin embargo, no logró escribir la otra parte del programa, ya que no se me ocurre cómo guardar el resultado de la división de forma de poder sumarlo luego (si tuviera las listas previamente escritas, tengo 4+7=11, por lo que coloco un 11MOD10=1 en el dígito de la unidad, y un 1+1+11DIV10 en el dígito de la decena).

Espero se hayan entendido mis ideas. Si alguien me pudiera ayudar a resolver el ejercicio, o me pudiera señalar algún error en el razonamiento planteado, se lo agradecería mucho.

Me disculpo si “mod” y “div” no son las expresiones correctas en el lenguaje que utilizamos, las expresé como las recuerdo del curso de Programación 1.

Muchas gracias de nuevo,

Romina.

En respuesta a Romina Belen Garcia Camargo

Re: Ejercicio 5, práctico 6

de Alex Elenter Litwin -

Buenas,

Te puedo decir +- como lo pense yo, y luego si un profesor me puede corregir mejor.

Dada la recursion podes asumir que el programa "sabe" calcular la suma de las "tails" de las dos listas. Entonces podes guardarte esa lista en una variable. Luego tendrias dos casos: 1) la longitud de la lista es igual a tus listas principales, ese es el caso que "te llevaste uno" por asi decirlo, o 2) que la longitud es menor, el caso mas facil. 
Osea que tendrias que hacer una funcion auxiliar longitud.

Luego si, podrias ver los casos a seguir despues, mi idea fue dividir en si la suma de lo que tengo que agregar al principio, es mayor a 20, mayor a 10 o "else".

Ojala te haya servido.

En respuesta a Alex Elenter Litwin

Re: Ejercicio 5, práctico 6

de Libertad Tansini -

Hola, general podemos pensar el problema de forma general antes de bajar a código, necesitamos considerar que para cada dígito de lista que sumamos, puede ser que reciba acarreo de la suma de dígitos menos significativos (carryA) y puede mandar acarreo para la suma de dígitos más significativos (carryD), algo así:

  • Sum ([x], [y]) = [x+y]    si x+y<10 y carryD = div(x+y) donde carryD es el accareo de x+y
  • Sum (x.Xs, y.Ys) = mod (x+y+carryA).Sum(Xs,Ys)  y carryD =  div(x+y+carryA) donde carryA es el accareo de Sum(Xs,Ys)

Para poder implementar esta función es necesario generalizar, es decir, la firma de  la función LDig suma(LDig l1, LDig l2); no alcanza porque no podemos representar el acarreo.

Por eso necesitaremos una función o procedimiento auxiliar que permita recibir el acarreo luego de la llamada recursiva, puede ser algo así:

void sumaCCarry ( LDig l1 , LDig l2 , LDig &suma , Digito & carry );

Otro dato importante que se usa en el caso base es la precondición de que los sumando son del mismo largo.

Saludos, libertad

En respuesta a Romina Belen Garcia Camargo

Re: Ejercicio 5, práctico 6

de Fernando Fernandez -

¿Pensaste en tener una función auxiliar que devuelva 2 valores: el mod, que sería una lista y el div, que es un número (podría ser bool porque es 0 o 1)?

En respuesta a Fernando Fernandez

Re: Ejercicio 5, práctico 6

de Romina Belen Garcia Camargo -

No se me ocurrió porque creo que llegar a los valores no sería muy complejo (quizá el código sea más claro haciendo funciones apartes, es verdad). Mi problema estaba en cómo conectar esos valores con lo que tengo, porque en mi caso base sumo el mod, y el div lo debería sumar en el caso siguiente (cosa que no sé cómo llevar a cabo).

Cuando decís una función auxiliar que devuelva dos valores, ¿te referís a dos funciones o a una función sola que devuelva dos cosas? En el caso de esto último, no sabría cómo hacerlo.


En respuesta a Romina Belen Garcia Camargo

Re: Ejercicio 5, práctico 6

de Fernando Fernandez -

Podés devolverlos con pasaje por referencia o podés crear un struct y devolverlo (en pascal no se podía)

void suma_aux (LDig l1, LDig l2, LDig & mod, bool & div);

o

struct modDiv_t {

   LDig mod;

   bool div;

};

modDiv_t suma_aux (LDig l1, LDig l2);


Una mezcla de ambas, que sería similar a lo que podrías hacer en Pascal es

void suma_aux(LDig l1, LDig l2, modDiv_t & modDiv);


Con, por ejemplo, la segunda versión la suma podría ser así:

LDig suma (LDig l1, LDig l2) {

   modDiv_t modDiv = suma_aux(lista l1, lista l2);

   Si modDiv.div entonces agregar 1 al principio de modDiv.mod

   devolver modDiv.mod

}


En respuesta a Fernando Fernandez

Re: Ejercicio 5, práctico 6

de Maria Alejandra Galetta Paz -

Buenas tardes, 

También tenía dudas respecto a este ejercicio, si bien entendí lo que han estado discutiendo, plantee una resolución sin usar las funciones de modulo o división. 

Lo que plantee fue lo siguiente, dado que la suma de dos números de un dígito solo puede llegar a la totalidad de 19 (teniendo en cuanta que se puede acarrear 1 de la anterior suma), puse como numero a almacenar en la lista nueva al dígito resultado de (suma-10), y el digito que almacené como variable fue uno.

Otra cosa que me quedo duda, es que a la función auxiliar es que le saque la precondición sobre que los sumandos sean listas vacías.

El código entonces lo plantee de la siguiente forma:

LDig sumaaux (LDig l1, LDig l2, int&d, LDig &resu) {

    if (empty (l1))

           return null();

   else {

              resu= sumaaux( tail(l1), tail(l2),d,resu);

              int suma= head(l1) + head (l2)+d;

              if (suma >=10) { 

                              resu=cons(suma-10,resu);

                              d=1;

               }else {

                          resu=cons (suma,resu);

                          d=0;

                        }

                `}

      return resu;

}

LDig suma (LDig l1, LDig l2) {

        int d=0;

        int resu= sumaaux ( l1, l2, d1, resu);

        if (d!=0)

              resu= cons (1,resu);

        return resu;

En respuesta a Maria Alejandra Galetta Paz

Re: Ejercicio 5, práctico 6

de Fernando Fernandez -

Me parece bien. Lo que sería un error es que en la función principal llamás a la auxiliar con la variable resu no definida.

En realidad sobra ese parámetro pasado por referencia o la función podría ser de tipo void. O sea, la función está devolviendo lo mismo por dos vías diferentes. Alcanza con una y sería mejor tener una sola, porque mantener ambas puede provocar errores. 

Respecto a considerar la lista vacía no te va a generar ningún error. Hacés una llamada de más  que no hace nada, cuando se podría controlar si las listas tienen un solo elemento. Puede ser cuestión de gustos.

Por último, más arriba, cuando se mencionaba mod y div no se quería decir que hubiera que usar esos operadores. Eran referencias a lo que, por ejemplo en tu código, representan resu y d desde un punto de vista conceptual.