• Blog
  • Productos
    • Cursos
    • Libros
    • Apps y Plugins
  • Academia
    • Ir a la Academia
    • Membresía Power Elite
    • Próximos Lanzamientos
Power SkillPower Skill
  • Blog
  • Productos
    • Cursos
    • Libros
    • Apps y Plugins
  • Academia
    • Ir a la Academia
    • Membresía Power Elite
    • Próximos Lanzamientos

Función del Lenguaje M para Convertir de Número Romano a Arábigo

10/10/2023 Posted by Miguel Caballero Lenguaje M


Los números romanos, históricamente significativos, se convierten a arábigos con herramientas modernas como Power Query, fusionando tradición y tecnología



Convertir de Número Romano a Arábigo con Power Query, una función personalizada de Power Query que desglosamos a continuación:

Paso 1: Definición de Variables

En este paso, establecemos las bases para nuestro código definiendo las variables esenciales que usaremos en los pasos posteriores.

                1 | let2 |     NumeroRomano = 3 |     "CMXXXVII",4 | 5 |     CodificacionRomana =  6 |     [ I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 ]7 | 8 | in9 |     CodificacionRomana            
lenguaje M Logo Power Query Zone

Número Romano

En nuestro código, la primera variable se llama NumeroRomano y almacenamos en ella un valor de tipo texto que representa el número romano CMXXXVII.

Codificación Romana

En nuestro código la variable CodifcacionRomana almacena un valor de registro. En el Lenguaje M, un registro es similar a un diccionario en otros lenguajes de programación, ya que asocia claves (en este caso, símbolos romanos) con valores (en este caso, sus equivalentes numéricos).

La CodificacionRomana mapea cada símbolo romano a su valor numérico correspondiente. Concretamente: “I” se asigna a 1, “V” se asigna a 5, “X” se asigna a 10 y así sucesivamente.

Paso 2: Validación de Símbolos

El propósito de este paso es garantizar que cada carácter en la cadena NumeroRomano sea un símbolo romano válido. Los símbolos romanos válidos incluyen “I”, “V”, “X”, “L”, “C”, “D” y “M”. Esto nos permite identificar de antemano cualquier entrada inválida, como por ejemplo “AVII“, donde la letra “A” no es un carácter válido dentro de la notación romana. La validación inicial es esencial para asegurarnos de que el número romano proporcionado sea correcto antes de continuar con cualquier proceso adicional.

Para lograrlo, primero:

Convertir Número Romano en Lista

Queremos que cada letra del número romano proporcionado sea un elemento en una lista. Esto lo conseguimos con la función Text.ToList. El resultado lo guardaremos en la variable NumeroRomanoEnLista, así: NumeroRomanoEnLista = Text.ToList ( NumeroRomano )

Validación de Caracteres Romanos

Luego de esto, procederemos a crear una expresión en un paso llamado EsValido que nos permitirá determinar si la lista NumeroRomanoEnLista contiene exclusivamente caracteres romanos válidos. Comenzamos utilizando la función List.Distinct aplicada a la variable NumeroRomanoEnLista, de manera que obtengamos una lista con valores únicos. A continuación, empleamos la función List.Difference para comparar esta lista de valores únicos con una lista predefinida de caracteres romanos válidos, que incluye: { "I", "V", "X", "L", "C", "D", "M" }.

Mediante esta expresión, logramos que la lista quede vacía si todos los elementos son caracteres romanos válidos; de lo contrario, si algún carácter no es válido (por ejemplo, una "A"), dicho carácter se mantendrá en la lista.

Para determinar si la lista resultante de la diferencia está vacía, empleamos la función List.IsEmpty. Si la lista está vacía, esto indica que todos los elementos en NumeroRomanoEnLista son caracteres romanos válidos, y la expresión devolverá true. Si la lista no está vacía, esto señala que al menos un elemento en NumeroRomanoEnLista no es un carácter romano válido, y la expresión devolverá false.

                 1 | let 2 |     NumeroRomano =  3 |     "CMXXXVII", 4 |  5 |     CodificacionRomana =   6 |     [ I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 ], 7 |  8 |     NumeroRomanoEnLista =  9 |     Text.ToList ( NumeroRomano ),10 | 11 |     EsValido =12 |     List.IsEmpty (13 |         List.Difference (14 |             List.Distinct ( NumeroRomanoEnLista ),15 |             { "I", "V", "X", "L", "C", "D", "M" }16 |         )17 |     )18 | 19 | in20 |     EsValido            
lenguaje M Logo Power Query Zone

Paso 3: Validación de Secuencia

Los números romanos tienen reglas específicas sobre cómo los símbolos individuales pueden aparecer en secuencia. Por ejemplo, el símbolo “I” puede repetirse hasta tres veces consecutivas (como en “III” para representar el número 3), pero nunca cuatro veces seguidas. De manera similar, los símbolos “V”, “L” y “D” tienen la restricción de que no deben repetirse en absoluto.

Enseguida crearemos una variable llamada EsSecuenciaValida, la cual utiliza La función List.Select para filtrar una lista predefinida de secuencias inválidas: { "IIII", "VV", "XXXX", "LL", "CCCC", "DD" } y selecciona solo aquellas secuencias que están presentes en NumeroRomano utilizando la función Text.Contains. El resultado es una lista de secuencias inválidas encontradas en NumeroRomano. Finalmente, la función List.IsEmpty verifica si esta lista resultante está vacía. Si la lista está vacía, significa que NumeroRomano no contiene ninguna secuencia inválida y la expresión devuelve true. Si la lista no está vacía, indica que hay al menos una secuencia inválida en NumeroRomano y la expresión devuelve false.

                 1 | let 2 |     NumeroRomano =  3 |     "CMXXXVII", 4 |  5 |     CodificacionRomana =   6 |     [ I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 ], 7 |  8 |     NumeroRomanoEnLista =  9 |     Text.ToList ( NumeroRomano ),10 | 11 |     EsValido =12 |     List.IsEmpty (13 |         List.Difference (14 |             List.Distinct ( NumeroRomanoEnLista ),15 |             { "I", "V", "X", "L", "C", "D", "M" }16 |         )17 |     ),18 | 19 |     EsSecuenciaValida = 20 |     List.IsEmpty (21 |         List.Select (22 |             { "IIII", "VV", "XXXX", "LL", "CCCC", "DD" },23 |             each 24 |             Text.Contains (25 |                 NumeroRomano, 26 |                 _27 |             )28 |         )29 |     )30 | 31 | in32 |     EsSecuenciaValida            
lenguaje M Logo Power Query Zone

Paso 4: Conversión de Romano a Arábigo

Ahora, vamos a convertir el número romano en su equivalente decimal. La idea es recorrer cada símbolo y, dependiendo del símbolo que le sigue, decidir si debemos sumar o restar su valor.

El fragmento de código EquivalenciaNumerica se encarga de convertir una lista de símbolos romanos en su equivalente numérico arábigo. Comienza verificando dos condiciones con EsValido and EsSecuenciaValida. Si ambas son verdaderas, procede a la conversión; de lo contrario, devuelve null.

La función List.Transform se utiliza para recorrer cada símbolo en NumeroRomanoEnLista. Para cada símbolo, determina su valor numérico (ValorActual) consultando el registro CodificacionRomana. Luego, identifica el símbolo siguiente (SimboloAdyacente) y su valor (ValorAdyacente). Si no hay un símbolo siguiente, se asigna un valor de -#infinity.

La lógica clave aquí es el cálculo de ValorConSigno. En la numeración romana, si un símbolo de menor valor precede a uno de mayor valor (como “IV” para 4), el valor del símbolo menor se resta del mayor. Por lo tanto, si ValorActual es menor que ValorAdyacente, se le asigna un signo negativo; de lo contrario, se mantiene su valor positivo.

El resultado es una lista de números que, cuando se suman, proporcionan el valor arábigo total del número romano.

                 1 | let 2 |     NumeroRomano =  3 |     "CMXXXVII", 4 |  5 |     CodificacionRomana =   6 |     [ I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 ], 7 |  8 |     NumeroRomanoEnLista =  9 |     Text.ToList ( NumeroRomano ),10 | 11 |     EsValido =12 |     List.IsEmpty (13 |         List.Difference (14 |             List.Distinct ( NumeroRomanoEnLista ),15 |             { "I", "V", "X", "L", "C", "D", "M" }16 |         )17 |     ),18 | 19 |     EsSecuenciaValida = 20 |     List.IsEmpty (21 |         List.Select (22 |             { "IIII", "VV", "XXXX", "LL", "CCCC", "DD" },23 |             each 24 |             Text.Contains (25 |                 NumeroRomano, 26 |                 _27 |             )28 |         )29 |     ),30 | 31 |     EquivalenciaNumerica = 32 |     if 33 |         EsValido and EsSecuenciaValida 34 |     then35 |         List.Transform (36 | 37 |             NumeroRomanoEnLista,38 | 39 |             ( Simbolo ) => 40 |             let41 |                 ValorActual = 42 |                 Record.Field ( 43 |                     CodificacionRomana, 44 |                     Simbolo45 |                 ),46 |                 47 |                 PosicionAdyacente = 48 |                 List.PositionOf ( 49 |                     NumeroRomanoEnLista, 50 |                     Simbolo51 |                 ) + 1,52 |                 53 |                 SimboloAdyacente = 54 |                 NumeroRomanoEnLista { PosicionAdyacente }?,55 |                 56 |                 ValorAdyacente = 57 |                 try 58 |                     Record.Field ( 59 |                         CodificacionRomana, 60 |                         SimboloAdyacente61 |                     ) 62 |                 otherwise 63 |                     -#infinity,64 |                 65 |                 ValorConSigno = 66 |                 if 67 |                     ValorActual < ValorAdyacente 68 |                 then 69 |                     -ValorActual 70 |                 else 71 |                     ValorActual72 |             in73 |                 ValorConSigno74 |         )75 |     else76 |         null77 | 78 | in79 |     EsSecuenciaValida            
lenguaje M Logo Power Query Zone

Paso 5: Cálculo Final

Finalmente, sumamos todos los valores numéricos para obtener el valor decimal del número romano.

Si EquivalenciaNumerica no es null (lo que significa que el número romano es válido), sumamos todos los valores para obtener el resultado final. De lo contrario, devolvemos null para indicar un número romano inválido.

Con estos pasos, hemos construido un código que no solo convierte números romanos a decimales, sino que también valida la entrada para asegurarse de que sea un número romano válido.

El código final:

                 1 | let 2 |     NumeroRomano =  3 |     "CMXXXVII", 4 |  5 |     CodificacionRomana =   6 |     [ I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000 ], 7 |  8 |     NumeroRomanoEnLista =  9 |     Text.ToList ( NumeroRomano ),10 | 11 |     EsValido =12 |     List.IsEmpty (13 |         List.Difference (14 |             List.Distinct ( NumeroRomanoEnLista ),15 |             { "I", "V", "X", "L", "C", "D", "M" }16 |         )17 |     ),18 | 19 |     EsSecuenciaValida = 20 |     List.IsEmpty (21 |         List.Select (22 |             { "IIII", "VV", "XXXX", "LL", "CCCC", "DD" },23 |             each 24 |             Text.Contains (25 |                 NumeroRomano, 26 |                 _27 |             )28 |         )29 |     ),30 | 31 |     EquivalenciaNumerica = 32 |     if 33 |         EsValido and EsSecuenciaValida 34 |     then35 |         List.Transform (36 | 37 |             NumeroRomanoEnLista,38 | 39 |             ( Simbolo ) => 40 |             let41 |                 ValorActual = 42 |                 Record.Field ( 43 |                     CodificacionRomana, 44 |                     Simbolo45 |                 ),46 |                 47 |                 PosicionAdyacente = 48 |                 List.PositionOf ( 49 |                     NumeroRomanoEnLista, 50 |                     Simbolo51 |                 ) + 1,52 |                 53 |                 SimboloAdyacente = 54 |                 NumeroRomanoEnLista { PosicionAdyacente }?,55 |                 56 |                 ValorAdyacente = 57 |                 try 58 |                     Record.Field ( 59 |                         CodificacionRomana, 60 |                         SimboloAdyacente61 |                     ) 62 |                 otherwise 63 |                     -#infinity,64 |                 65 |                 ValorConSigno = 66 |                 if 67 |                     ValorActual < ValorAdyacente 68 |                 then 69 |                     -ValorActual 70 |                 else 71 |                     ValorActual72 |             in73 |                 ValorConSigno74 |         )75 |     else76 |         null,77 |     78 |     CalculoDelValor = 79 |     if 80 |         EquivalenciaNumerica <> null 81 |     then 82 |         List.Sum ( EquivalenciaNumerica ) 83 |     else 84 |         null    85 |     86 | in87 |     CalculoDelValor            
lenguaje M Logo Power Query Zone

Y aquí lo tenemos la solución complete para Convertir de Número Romano a Arábigo con Power Query.

Conclusiones

La conversión de números romanos a arábigos, aunque puede parecer una tarea arcaica, sigue siendo relevante en la era digital, especialmente cuando se trata de procesar y analizar datos en la parte de derecho, recursos humanos y sus formatos, documentos históricos y literarios. El fragmento de código que hemos explorado demuestra la potencia y flexibilidad de Power Query para abordar este desafío.

Si deseas aprender Power Query y Lenguaje M y crear soluciones como Convertir de Número Romano a Arábigo con Power Query, el curso de Grado Experto: Experto en Power Query y Lenguaje M es la mejor opción.

Share
6

You also might be interested in

Análisis de Datos Instantáneo: Descubre las Tablas Dinámicas Recomendadas de Excel

Ene 2, 2024

Análisis de datos instantáneo: Descubre y explora las Tablas Dinámicas recomendadas de Excel y cómo configurar sus campos.

¿Desbancará un Lenguaje de Programación Natural a Python en Popularidad?

Oct 31, 2023

La Evolución Incesante: Del Código a la Conversación. ¿Python no[...]

Últimas Innovaciones de DAX: Eleva tu Juego en Power BI con las Funciones INFO DAX

Dic 23, 2023

Descubre cómo las funciones INFO DAX en Power BI ponen a disposición de información acerca del modelo semántico gracias a la vista de consultas DAX.

Nuevo Mensaje!

No estamos disponibles en estos momentos, por favor déjanos un mensaje, te responderemos lo antes posible, ¡Gracias!

Envíar Mensaje
Academia de Power Skill ¡Quiero ir Ahora!

Información de Contacto

  • Power Skill
  • Coworking ocasional: HubBog
  • (+57) 313 353 47 56
  • excelfreebymcs@gmail.com
  • https://powerskill.tech/

Social Icons Widget

Copyright © 2023 - 2025 | Power Skill & Power Skills • Todos los derechos reservados.

  • Blog
  • Productos
    • Cursos
    • Libros
    • Apps y Plugins
  • Academia
    • Ir a la Academia
    • Membresía Power Elite
    • Próximos Lanzamientos