Ayudante de números romanos




El siguiente desafío fue extraído de la página de codewars. Al final del post les dejo el enlace del desafío para que lo completen si asi lo desean.

NOTA: Para pasar este desafío solo es necesario que los métodos conviertan valores decimales 1 a 3999 y viceversa ya que los casos de prueba arrojan valores inferiores al valor antes mencionado.

Planteo del problema:


Cree una clase RomanNumerals que pueda convertir un número romano en un valor entero. Debe seguir la API que se muestra en los ejemplos siguientes. Se probarán varios valores de números romanos para cada método auxiliar.
Los números romanos modernos se escriben expresando cada dígito por separado comenzando con el dígito más a la izquierda y omitiendo cualquier dígito con un valor de cero. En números romanos se representa 1990: 1000 = M, 900 = CM, 90 = XC; resultando en MCMXC. 2008 se escribe como 2000 = MM, 8 = VIII; o MMVIII. 1666 usa cada símbolo romano en orden descendente: MDCLXVI.
En este kata 4 debe representarse como IV, NO como IIII(los "cuatro del relojero").
Ejemplos de
RomanNumerals.to_roman(1000) # should return 'M'
RomanNumerals.from_roman('M') # should return 1000


Algunas consideraciones de los números romanos

  1. Una letra no puede repetirse más de tres veces.
  2. una letra con un valor bajo que este antes de una letra con mayor valor se considera una resta. Por ejemplo IV.
  3. A la regla anterior se le suma que no puede haber más de dos letras del mismo valor. Por ejemplo el 8 se lo representa VIII, no se lo puede representar así IIX.

Hay que crear una clase llamada RomanNumerals con dos métodos estáticos (to_roman y from_roman). Coloque los valores decimales y romanos en un diccionario para tener esa equivalencia. 
Ahora para el metodo to_roman el valor que me ingresa lo convierto a un string y voy tomando el primer valor y el resto de valores se rellenan con ceros porque va a terminar cayendo en uno de los diccionarios. Eje


1  9  9  0 = 1000
    9  9  0 = 900
        9  0 = 90
            9 = 9
Los valores 1000, 900,90,9 son claves en distintos diccionarios.


Codigo del metodo to_roman




Para el método from_roman lo que hice fue agrupar los diccionarios e invertir las claves pasan hacer valores decimales y los valores pasan hacer las claves en romano. 
Primero tomo un valor y después tomo el próximo valor. Consulto el diccionario y si el valor decimal que obtengo con el primer valor es menor que el segundo valor decimal entonces hago un resta y eso es lo que se acumula. ej

    I  V
            1 - 5 = 4

Explicación del método to_roman


Declaro 4 diccionarios.
Convierto el parámetro num_decimal para ir extrayendo un dígito distinto de cero e ir concatenando ceros para obtener una clave que se que va a estar en un diccionario.
Voy verificando la longitud para determinar si es un dígito de 4,3,2 o 1 cifra.
Multiplicó 1000 por el valor que tengo en el índice 0 de la cadena. Después aplico un rebanado para convertir el valor de 4 dígitos en un valor de 3 dígitos. Al ir achicando esa cadena va ir ingresando a cada uno de los if .




En el segundo y tercer if (contando de arriba hacia abajo) tiene una variable n que va almacenar la clave de la letra.
La variable value_roman obtiene la división de la letra para multiplicar la cadena y vuelvo a formatear la cadena.


Explicación del método from_roman


Llamo a un función invest(en este caso está fuera de la clase) que lo que hace es tomar los 4 diccionarios invertir los valores (ahora la clase es el número romano y el valor es el número decimal) 




ACLARACIÓN: La función invest esta fuera de la clase por que el test levantaba un aserción sí esa función estaba en la clase. Perfectamente puede ser un método estático.




NOTA: Al entrar al bucle, en la última pasada del bucle la variable index al evaluar el if daría un IndexError para evitar tomó la longitud de la cadena-1.
Si el el primer valor es mayor o igual al segundo valor tomado, consulto en el diccionario y acumulo el valor.

Codigo completo



Resultados






Te dejo este conversor para que pruebes el código o verifique los ejemplos.
Este es el Kata 


¡Saludos!

Comentarios