Reto día 13/100 con Python
Tags: spanish, codenewbie, 100daysofcode, python
Published: 2021-02-07 04:22:50

### Mínimo Común Múltiplo y Máximo Común Divisor

Ejercicio 1: 
 * Crear un programa que permita elegir al usuario si desea calcular el m.c.m. o el m.c.d. 
 * El usuario solo puede ingresar dos números para calcular la opción elegida.
 * El programa debe mostrar el resultado final.

 Nota: Durante el desarrollo del ejercicio se observó que existen varias maneras de calcular tanto el m.c.m como el m.c.d. y se trató de realizar el código con menos líneas, sin embargo podría reducirse más ya que python tiene una función dentro del módulo `math` llamado `gcd()` el cual calcula el m.c.d. sin embargo solo ahorraría 2 líneas teniendo en cuenta que puedo calcular primero el m.c.m. y con ello luego el m.c.d.; también existe una función llamada `lcm()` para calcular el m.c.m. que también recibe dos números pero solo esta disponible a partir de la versión 3.9 de python y actualmente este programa funciona con la versión 3.8

La idea con este ejercicio es poder practicar el uso de funciones. Por eso para hallar el m.c.m. primero creo una función destinada a ello que recibe dos parámetros. La lógica utilizada en su desarrollo se basó en las hojas de excel donde al colocar ambos números desde la misma fila y aplicar una fórmula donde se vaya sumando la casilla siguiente hacia abajo con la primera que contiene el valor original se va a crear una secuencia acumulativa en donde en algún punto ambos números coincidiran en el valor del múltiplo:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gazjqbye8xah90b96vcw.png)

Siguiendo esa lógica se harán sumas a ambas variables hasta que por primera vez coincidan, para este ejemplo ambas coincidieron en el valor 1620, sin embargo, cada una lo logró en una fila diferente. En cada iteración entonces solo voy a sumar el valor original al acumulado cuando sea menor que la otra variable. Al final regresará el valor final que coincidieron el cual sería el mínimo común múltiplo. A la función le doy el nombre de `encontrar_mcm(m,n)`

```python
def encontrar_mcm(m,n):
    m_max=m
    n_max=n
    mcm = 0
    while m_max != n_max:
        if n_max < m_max:
            n_max += n
        elif m_max < n_max:
            m_max += m
    if m_max == n_max:
        mcm = m_max
    return mcm
```
En cuanto a encontrar el máximo común divisor no puedo aplicar la misma regla o lógica ya que es un caso contrario donde en lugar de ir aumentando tengo que ir disminuyendo el valor hasta encontrar el número más alto que divida a ambos números. Encuentro en su lugar que si yo divido el m.c.m. entre cualquiera de los dos números que entrega el usuario,  obtengo un resultado que me sirve para dividir el otro número ingresado y de esa forma obtengo el valor que estoy buscando m.c.d. y llamo a este método encontrar_mcd(m,n):
```python
def encontrar_mcd(m,n):
    mcm = encontrar_mcm(m,n)
    mcd = m/(mcm/n)
    return mcd
```
### Números primos
 Ejercicio 2:
 * Programa que permita conocer los factores primos que pertenecen a un número entregado por el usuario y cuantas veces se repite cada uno.
 * Para realizar este ejercicio se toma en cuenta que los números primos son aquellos que solo son divisibles entre 1 y el mismo número, por lo que si llega a ser divisible por otro número menor a él mismo entonces no es primo.
 * Se mostrará en pantalla cada factor con su correspondiente exponente

Este ejercicio resulta un poco más largo que el anterior. Inicialmente quería partir de este código para poder encontrar el mínimo común múltiplo ya que dentro del campo de las matemáticas el método para hacerlo es descomponer los dos números en sus factores primos, sin embargo me pareció algo largo y por eso decidí dejar este para lo último. Todavía desconozco si python tiene alguna función propia que determine este resultado pero la idea de realizar este ejercicio es practicar el uso de la lógica para solucionar problemas mediante algoritmos trabajados en código.

La solución sigue el siguiente orden de métodos:

1. evaluar_primos(numero) - determina si un número dado es o no primo. Si ya hemos revisado la teoría de los números primos sabremos que un número primo es aquel que solo se divide por 1 y por sí mismo, pero inicialmente partiendo del número más pequeño después del 1, siguen en su orden los números 2 y 3 que también se clasifican de la misma manera. A partir de ahí ya hay saltos y no hay primos tan seguidos. Por lo tanto la condición que permite saber si lo es o no es que siendo mayor de 3 no sea divisible por otro número iterando el divisor de uno en uno hasta llegar al número anterior al valor final. El resultado debe retornar True si es primo, False si no lo es:

    ```python
def evaluar_primos(numero):            
    for evalua_primo in range(2,numero):
        if numero > 3 and numero % evalua_primo == 0:            
            return False                        
    return True
    ```


2. lista_primos(numero_dividendo) - método encargado de obtener los factores primos únicos que dividen a un número. Estos serían los factores primos base. Estos factores los voy guardando en una lista a medida que los identifique si el numero_dividendo es 2 o mayor y al dividirlo entre determinado número su residuo es igual a cero (0) evaluamos, llamando al método evaluar_primos(numero_divisor) si es primo para almacenarlo en la lista de la función. Este método retorna una lista primos. Esto se maneja mediante una iteración que parte desde el número 2 hasta que el numero_dividendo sea exactamente el valor que ingreso el usuario.

    ```python
    def lista_primos(numero_dividendo):
        primos=[]
        for numero_divisor in range(2, numero_dividendo+1):
            if numero_dividendo >= 2 and numero_dividendo % numero_divisor == 0 :            
                if evaluar_primos(numero_divisor):
                    primos.append(numero_divisor)
        return primos
    ```
3. divisores_primos(numero_dividendo) - al igual que el anterior método entrega una lista de números primos pero los entrega todos con repetición. Por ejemplo al averiguar los factores primos del número 8 obtenemos que los factores primos que lo dividen son 2*2*2 = 8, por lo que la lista de este método nos aparecerá [2,2,2], mientras que en el anterior método aparecerá una lista [2]. El objetivo es diferente para cada lista. En la primera tengo el primo base y en la lista de este método obtengo el número de veces que aparece cada factor que al contarlos serían lo mismo que el exponente.

    Para obtener esta lista procedo de la siguiente forma:
    * numero_cociente tendrá iniciamente el valor de numero_dividento
    * Creo una lista vacía para los factores primos que vaya encontrando.
    * Itero desde el número 2 hasta que sea igual al número entregado por el usuario.
    * Dentro de la iteración resuelvo mientras que el numero_dividendo dividido entre el iterador numero_divisor tengan un residuo igual a cero (0)
    * Mientras que la anterior afirmación del ciclo se cumpla voy guardando el valor del numero_divisor en la lista del método.
    * Encuentro el siguiente número cociente dividiendo numero_cociente entre numero_divisor.
    * Con el resultado anterior reviso que si el numero_cociente al dividirlo entre numero_divisor tiene un residuo diferente de cero 
    * Si se cumple la anterior condición salgo de este ciclo y cambio el valor del número divisor para volver a comenzar un nuevo ciclo, pero si no se cumple la condición quiere decir que el numero_divisor también es factor primo para el nuevo numero_cociente y toca guardarlo en la lista.
    * Cuando el numero_cociente tenga un valor igual a cero dejará de ejecutarse el iterador y quedaría completada toda la lista de factores primos.

    ```python
    def divisores_primos(numero_dividendo):
        numero_cociente = numero_dividendo
        lista_primos = []
        for numero_divisor in range(2,numero_dividendo+1):
            while numero_dividendo % numero_divisor == 0:
                lista_primos.append(numero_divisor)
                numero_cociente = numero_cociente / numero_divisor
                if numero_cociente % numero_divisor != 0:
                    break
            if numero_cociente == 0:
                break
        return lista_primos
    ```

4. factores_primos(numero_dividendo) - Método encargado de guardar los resultados de las dos listas anteriores en un diccionario. No tiene mayor explicación. La clave guardará los valores de la lista de factores unicos, mientras que el valor del diccionario almacenará el exponente del factor primo contando cuantos factores del mismo valor aparecen en la lista entregada por el método divisores_primos(numero_dividendo).

    ```python
    def factores_primos(numero_dividendo):
        factores_unicos = lista_primos(numero_dividendo)
        total_factores = divisores_primos(numero_dividendo)
        cantidad_factores = {}    
        for factor in factores_unicos:
            cantidad_factores[factor] = total_factores.count(factor)
        return cantidad_factores     
    ```

Pueden revisar el código completo en [Github](https://github.com/WilsonGLan/Reto_100_dias/tree/main/dia_13)

El código mostrado es de mi autoría por lo que siendo principiante estoy seguro que se puede mejorar este código. Por favor dime como piensas que puedo mejorarlo.