PISTAS PARA EL EJERCICIO 3 (ENTREGA 10)

 

En primer lugar las definiciones, para aquellos a los que haya pillado desprevenidos:

 

El factorial de un número es el resultado de multiplicar sucesivamente este número por todos aquellos que sean inferiores, hasta la unidad. Por ejemplo, el factorial de 4 (que se escrbie 4!) es 4*3*2*1.

 

El máximo común divisor de dos números es el número más grande entre el que que se pueden dividir ambos obteniendo resto cero. Por ejemplo, el máximo común divisor de 12 y 18 es 6, puesto que 18/6 es 3 con resto cero y 12/6 es 2 con resto cero, y ningún número mayor que seis es divisible entre los dos. Lógicamente, el máximo común divisor puede coincidir con el menor de los números. Por ejemplo, el máximo común divisor entre 6 y 12 es 6, puesto que 6/6 es 1 con resto cero y 12/6 es 2 con resto cero.

 

El mínimo común múltiplo entre dos números es el más pequeño que se puede dividir entre los dos obteniendo resto cero. Por ejemplo, el mínimo común múltiplo entre 9 y 6 es 18, porque 18/9 es 2 con resto cero y 18/6 es 3 con resto cero, y no hay ningún número menor que 18 que también sea divisible entre los dos. Lógicamente, el mínimo común múltiplo puede ser igual al mayor de ellos. Por ejemplo, el mínimo común múltiplo entre 6 y 12 es 12.

 

Un número es perfecto cuando la suma de todos sus divisores a excepción de él mismo es igual a él. Por ejemplo, el 6 es perfecto, porque la suma de todos sus divisores excepto él mismo es también 6 (1+2+3).

 

Bueno, y ahora con las pistas propiamente dichas, aunque realmente no voy a dar demasiadas (que luego "to" se sabe). Solamente te indicaré cómo calcular el máximo común divisor con un método recursivo.

 

El método rMCD tiene que ser recursivo. Veamos, una de las formas de calcular el máximo común divisor es la siguiente: si los dos números son iguales, el MCD es cualquiera de ellos. De lo contrario al mayor se le resta el menor y se comprueba si la diferencia es igual al menor. Si no, lo mismo. Por ejemplo, entre 63 y 18, como no son iguales se restan: 63-18, que es 45 y se vuelve a hacer la comprobación entre los dos números (45 y el menor de los anteriores, o sea, 18). Como no son iguales, se vuelven a restar: 45-18, que es 27 y se vuelve a comprobar (27 y el menor de los anteriores, o sea, 18 nuevamente). Como siguen sin ser iguales, se vuelve a hacer la resta: 27-18, que es 9, y se vuelve a comprobar (9 y el menor de los anteriores, o sea, 18). Siguen sin ser iguales, pero recuerda que ahora el mayor es 18 y el menor es 9. Se vuelven a restar: 18-9 que es 9. Ahora la diferencia es igual que el menor de los dos números, por lo que ya tenemos el MCD: 9.

 

RESOLUCIÓN DEL EJERCICIO

 

Bueno, aquí lo tenéis. Ciertamente, es un poquito largo, pero nada comparado con un programa de verdad, ¿no te parece? El código está comentado para que no os cueste mucho descifrarlo.

 

using System;

 

namespace Ejercicio3

{

    class Metodos

    {

        public static double rFact(byte num)

        {

            // Basta con usar el operador QUESTION (?:) en lugar de if

            return (num==0) ? 1 : num * rFact((byte) (num-1));

        }

 

        public static double itFact(byte num)

        {

            /* Aquí necesitaremos un bucle que vaya haciendo las sucesivas

             * multiplicaciones hasta encontrar el factorial */

            double Fact=1;

 

            for (byte i=2;i<=num;i++)

                Fact *= i;

 

            return Fact;

        }

 

        public static ulong rMCD(ulong num1, ulong num2)

        {

            /* Primero se calcula cuál de ellos es mayor y cuál es menor.

             * En caso de que sean iguales, mayor y menor van a valer lo

             * mismo.    */

            ulong mayor=(num1>num2) ? num1 : num2;

            ulong menor=(num1>num2) ? num2 : num1;

 

            /* Examinemos este return: si son iguales retornará mayor.

             * En realidad hubiera sido lo mismo que retornara menor,

             * puesto que, recuerda, son iguales. En caso contrario

             * se vuelve a calcular el MCD, esta vez entre la diferencia

             * de ellos y el menor. Esto se repetirá hasta que sean

             * iguales    */

            return (mayor==menor) ? mayor : rMCD(mayor-menor, menor);

        }

 

        public static ulong itMCD(ulong num1, ulong num2)

        {

            /* Aquí también necesitamos saber cuál es el mayor y cuál el

             * menor, recordando siempre que si son iguales se retornará

             * cualquiera de ellos    */

            ulong mayor=(num1>num2) ? num1 : num2;

            ulong menor=(num1>num2) ? num2 : num1;

 

            if (mayor==menor) return mayor;

 

            /* Se asigna la mitad del mayor al posible MCD porque,

             * lógicamente, ningún número mayor que la mitad del mayor de

             * los dos será divisible entre este, o sea, si el mayor es,

             * por ejemplo, 8, ningún número mayor que 4 (o sea, la mitad

             * de 8) será divisible entre 8. Así nos ahorramos al menos

             * la mitad de las operaciones    */

            ulong MCD=mayor/2;

 

            /* Este bucle va reduciendo MCD en una unidad mientras no

             * sea divisible entre los dos. Cuando lo sea, el bucle no se

             * itera y se devuelve MCD    */

            while (mayor % MCD!=0 || menor % MCD!=0)

            {

                MCD-=1;

            }

 

            return MCD;

        }

 

        public static ulong MCM(ulong num1, ulong num2)

        {

            /* En este caso no sería necesario ver cuál es el mayor

             * y cuál es el menor, pero calcularlo nos ayuda a evitar

             * muchas operaciones, pues de lo contrario tendríamos que

             * ir comprobando números desde 1 hasta que se encontrara

             * el MCM.    */

            ulong mayor=(num1>num2) ? num1 : num2;

            ulong menor=(num1>num2) ? num2 : num1;

 

            /* Dado que el menor de los múltiplos comunes de dos números

             * tiene que ser, como mínimo, igual que el mayor, asignamos a

             * la varable mcm lo que vale el mayor de los dos.    */

            ulong mcm=mayor;

 

            /* Este bucle puede ser algo confuso, pero en realidad es el

             * ideal. Efectivamente, evito hacer demasiadas operaciones

             * calculando si los sucesivos múltiplos del mayor lo son

             * también del menor, en cuyo caso se ha encontrado. */

            while (mcm % menor !=0)

                mcm+=mayor;

 

            return mcm;

        }

 

        public static bool EsPerfecto(ulong num)

        {

            /* Nos hace falta esta variable para ir almacenando los

             * divisores del número en cuestión    */

            ulong sumadiv=0;

 

            /* Este bucle recorre todos los números desde la unidad hasta

             * la mitad del número en cuestión. ¿Porqué hasta la mitad?

             * Pues porque ningún número mayor de la mitad puede ser

             * uno de sus divisores, lógicamente. Luego, si el número

             * por el que vamos iterando es divisor de num se suma a

             * sumadiv, y si no a sumadiv se le suma 0, o sea, nada    */

            for (ulong i=1;i<=num/2; i++)

                sumadiv += (num % i==0) ? i : 0;

 

            /* Aquí podríamos haber usado un QUESTION o un if, pero esto

             * es suficiente, puesto que hay que retornar precisamente el

             * resultado de la comparación, es decir, si son iguales hay

             * que retornar true, y si no lo son hay que retornar false    */

            return sumadiv==num;

        }

    }

 

    class MetodosApp

    {

        static void Main()

        {

            ulong num1=0;

            ulong num2=0;

 

            do

            {

                try

                {

                    Console.Write("Dame un número para calcular el factorial: ");

                    num1=UInt64.Parse(Console.ReadLine());

                }

                catch

                {

                    continue;

                }

            } while (num1>255);

 

            Console.WriteLine("El método rFact dice que el factorial de {0} es {1}",

                num1,Metodos.rFact((byte) num1));

            Console.WriteLine("El método rFact dice que el factorial de {0} es {1}",

                num1,Metodos.itFact((byte) num1));

 

            Console.WriteLine();

 

            do

            {

                try

                {

                    Console.Write("Ahora dame uno de los números mara MCD y MCM: ");

                    num1=UInt64.Parse(Console.ReadLine());

                    Console.Write("Ahora dame el otro número mara MCD y MCM: ");

                    num2=UInt64.Parse(Console.ReadLine());

                }

                catch

                {

                    continue;

                }

            } while (num1==0 || num2==0);

 

            Console.WriteLine("El método rMCD dice que el MCD entre {0} y {1} es {2}",

                num1, num2, Metodos.rMCD(num1, num2));

            Console.WriteLine("El método itMCD dice que el MCD entre {0} y {1} es {2}",

                num1, num2, Metodos.itMCD(num1, num2));

 

            Console.WriteLine();

 

            Console.WriteLine("El método MCM dice que el MCM entre {0} y {1} es {2}",

                num1, num2, Metodos.MCM(num1, num2));

 

            Console.WriteLine();

 

            do

            {

                try

                {

                    Console.Write("Por fin, dame un número para ver si es perfecto: ");

                    num1=UInt64.Parse(Console.ReadLine());

                }

                catch

                {

                    continue;

                }

            } while (num1>255);

 

            Console.WriteLine("El método EsPerfecto dice que el número {0} {1}",

                num1, Metodos.EsPerfecto(num1) ? "es perfecto": "no es perfecto");

 

            string a=Console.ReadLine();

        }

    }

}

 

Sigue este vínculo si quieres bajártelo.