El desafío es hacer que cualquier código romano sea válido en el idioma elegido.
Deben no aparecer dentro de cadenas o cualquier cosa similar, pero funcionan igual que cualquier otro fichas, literales tales como ( árabe ) números, caracteres o cadenas; o identificadores de variable / método / función, etc.
Por ejemplo, en Java, lo siguiente debería compilarse y ejecutarse como si i
se hubiera inicializado a 42
:
int i = XLII;
El análisis real de los números es secundario, por lo que puede usar una biblioteca si lo desea, pero este es un concurso de popularidad, por lo que se fomenta la creatividad.
No puede usar ningún idioma que realmente use números romanos, si existe tal cosa.
Buena suerte.
Process
ast
para analizar la fuente. Inserte en la parte superior del AST la definición de los números romanos del 1 al 3999. Compile todo y ejecútelo. Es aburrido escribir el código para manejar el proceso.Respuestas:
do
Hay solo unos pocos números romanos, ya que 4000 y superiores no tienen notación estándar, y el preprocesador es una herramienta de descompresión maravillosa, especialmente si no tiene problemas con el hecho de que el código tiene un comportamiento indefinido.
Esto define todos los números romanos desde
I
hastaMMMCMXCIX
como constantes de enumeración, más_
(que puede ser reemplazado por cualquier cosa que desee) como cero.fuente
scanf
también :) @ klingt.net No estoy seguro de qué tipo de ejemplo estás buscando. Una bastante simple seríaint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
Rubí
Todos los números romanos (mayúsculas) ahora se analizarán como sus equivalentes decimales. El único problema es que todavía son asignables: puedes hacerlo
X = 9
, pero no10 = 9
. No creo que haya una manera de arreglar eso.fuente
JavaScript (ES6)
Úselo
Proxy
para atrapar números romanos.Probable en Firefox (más reciente) en JSFiddle .
No es comprobable en Chrome (con Traceur) ya que la
Proxy
implementación no funciona.Uso:
fuente
C y C ++ (respuesta actualizada)
Como se observó en un comentario, mi solución original tenía dos problemas:
Como quería que mi código fuera lo más genérico posible para trabajar en plataformas más antiguas, decidí darle otra puñalada. Es más largo que antes, pero funciona en compiladores y preprocesadores configurados en modo de compatibilidad C89 / C90. Todas las macros pasan un número apropiado de argumentos en el código fuente, aunque a veces esas macros se "expanden" en nada.
Visual C ++ 2013 (también conocido como versión 12) emite advertencias sobre parámetros faltantes, pero ni mcpp (un preprocesador de código abierto que afirma un alto cumplimiento del estándar) ni gcc 4.8.1 (con -std = iso9899: 1990 -conmutadores de errores pedagógicos) emiten advertencias o errores para esas invocaciones macro con una lista de argumentos efectivamente vacía.
Después de revisar el estándar relevante (ANSI / ISO 9899-1990, 6.8.3, Reemplazo de macros), creo que hay suficiente ambigüedad para que esto no se considere no estándar. "El número de argumentos en una invocación de una macro similar a una función debe coincidir con el número de parámetros en la definición de macro ...". No parece excluir una lista de argumentos vacía siempre que los paréntesis necesarios (y las comas en el caso de múltiples parámetros) estén en su lugar para invocar la macro
En cuanto al problema de coma final, eso se resuelve agregando un identificador adicional a la enumeración (en mi caso, MMMM que parece tan razonable como cualquier cosa para que el identificador siga 3999 incluso si no obedece las reglas aceptadas de secuenciación de números romanos exactamente).
Una solución ligeramente más limpia implicaría mover la enumeración y admitir macros a un archivo de encabezado separado, como se implica en un comentario en otro lugar, y usar undef de los nombres de macro inmediatamente después de que se usaron para evitar contaminar el espacio de nombres. Indudablemente, también deberían elegirse mejores nombres de macro, pero esto es adecuado para la tarea en cuestión.
Mi solución actualizada, seguida de mi solución original:
La respuesta original (que recibió los primeros seis votos a favor, por lo que si nadie vuelve a votar esto, no debería pensar que mi solución actualizada obtuvo los votos a favor):
En el mismo espíritu que una respuesta anterior, pero de una manera que debería ser portátil utilizando solo un comportamiento definido (aunque los diferentes entornos no siempre coinciden en algunos aspectos del preprocesador). Trata algunos parámetros como opcionales, ignora otros, debería funcionar en preprocesadores que no admitan la
__VA_ARGS__
macro, incluido C ++, utiliza macros indirectos para garantizar que los parámetros se expandan antes de pegar el token, y finalmente es más corto y creo que es más fácil de leer ( aunque todavía es complicado y probablemente no sea fácil de leer, solo que más fácil):fuente
__VA_ARGS__
.Lisp común
La siguiente es una explicación bastante extensa de cómo hice una macro que puedes usar así:
Cuando se llama a una macro en Common Lisp, básicamente actúa como una función, solo que los argumentos se reciben antes de ser evaluados. En realidad, dado que en Common Lisp el código es solo información, lo que recibimos es una lista (anidada) que representa un árbol de sintaxis sin analizar con el que podemos hacer lo que queramos, y se realiza en tiempo de compilación.
Funciones de ayuda
El primer paso del plan es tomar este árbol y escanearlo en busca de algo que se parezca a los números romanos. Siendo Lisp y todo, intentemos hacerlo de manera funcional: necesitamos una función que haga un recorrido profundo de un árbol y devuelva cada objeto para el que una función proporcionada
searchp
devuelve verdadero. Este es incluso (semi) recursivo de cola.Luego, un código para analizar los números romanos, cortesía de Rosetta Code :
La macro real
Tomamos el árbol de sintaxis (
body
), lo buscamos con nuestro procedimiento de búsqueda profunda y de alguna manera hacemos que los números romanos que encontramos estén disponibles.Entonces que es
1 + 2 + 3 + (4 * (5 + 6)) + 7
?Y para ver qué sucedió realmente cuando se invocó la macro:
fuente
Lua
Simplemente un __index alternativo para la tabla global. La conversión real usando gsub resultó mucho más bonita de lo que imaginé.
fuente
Posdata
Traté de seguir el C pero no lo entendí. Entonces lo hice de esta manera:
PostScript no tiene,
enum
pero podemos construir un diccionario con valores enteros secuenciales y plegarlos en una matriz. Esto reduce el problema a generar todas las cadenas en secuencia, lo que se hace concatenando en 4 bucles anidados. Por lo tanto, genera todas las cadenas, luego intercala cada cadena con un valor de contador creciente, lo que resulta en una larga serie de pares <string> <int> en la pila que se envuelven en<<
...>>
para producir un objeto de diccionario.El programa construye e instala un diccionario que asigna todos los nombres de los números romanos a su valor correspondiente. Entonces, mencionar los nombres en el texto de origen invoca la búsqueda automática de nombres y produce el valor entero en la pila.
huellas dactilares
fuente
Smalltalk (Smalltalk / X) (87/101 caracteres)
por supuesto, podríamos modificar fácilmente el tokenizer del analizador (ya que es parte de la biblioteca de clases, y como tal está abierto a modificaciones, y siempre está presente), pero un desafío es afectar solo las evaluaciones en un contexto dado, de modo que el resto del El sistema funciona como siempre.
Versión 1:
definir una serie de variables en el espacio de nombres de evaluación. Esto afectará a los doIts interactivos (también conocidos como evals):
entonces puedo hacer (en un doIt, pero no en el código compilado):
-> 2019
Aviso: los 101 caracteres incluyen espacios en blanco; en realidad se puede hacer con 87 caracteres.
También tenga en cuenta que, cuando se define en el espacio de nombres Smalltalk global, vería esas constantes también en el código compilado.
Versión 2:
Use un gancho methodWrapper, que permite envolver cualquier código existente sin volver a compilar. Lo siguiente envuelve el tokenizador del analizador para buscar un identificador romano para escanear y lo convierte en un número entero. La parte difícil es detectar dinámicamente si el contexto de llamada es del imperio romano o no. Esto se hace usando una señal de consulta (que técnicamente es una excepción procesable):
define la consulta:
Por lo tanto, podemos solicitar en cualquier momento ("consulta InRomanScope") que sea falso por defecto.
Luego, envuelva el método checkIdentifier del escáner:
Ahora el escáner funciona como de costumbre, a menos que estemos en el imperio romano:
-> 2525
incluso podemos compilar código:
buen intento; pero esto falla con un error de sintaxis (que es exactamente lo que queremos). Sin embargo, en el imperio romano, podemos compilar:
y ahora, podemos preguntarle a cualquier número entero (enviando ese mensaje) desde dentro y fuera de Roma:
-> 2525
fuente
Haskell, utilizando metaprogramación en Template Haskell y números romanos :
Haskell reserva identificadores que comienzan con letras mayúsculas para los constructores, por lo que utilicé minúsculas.
fuente
J - 78 char
Esto solo sube a MMMCMXCIX = 3999, como con las otras soluciones.
Desglosándolo (recordar J generalmente se lee de derecha a izquierda, a menos que sea reemplazado por paréntesis):
M`CDM`XLC`IVX
- Cuatro cajas de letras. Vamos a utilizar matrices numéricas en el índice de estas letras y construir subpalabras de números romanos.841,3#79bc5yuukh
- Estos son los datos numéricos, fuertemente codificados. *(_1,~3#.inv])
- Esto decodificará los datos anteriores, expandiéndolos en ternario y agregando -1.('';&;:(...){' ',[)&.>
- Emparejando los números de la izquierda con los cuadros de la derecha (&.>
), decodifica los conjuntos de números y úsalos para indexar las letras. Tratamos 0 como espacio anteponiendo un carácter de espacio a las listas de letras. Este procedimiento crea listas de palabras comoI II III IV V VI VII VIII IX
yM MM MMM
.{
- Tome el producto cartesiano de estas cuatro cajas llenas de palabras. Ahora tenemos una matriz 4D de todos los números romanos.}.,;L:1
- Ejecute todo eso en una sola lista 1D de números romanos y elimine la cadena vacía en la parte delantera porque crearía un error. (¡L:
Es una vista rara en J golf! Por lo general, no hay tantos niveles de boxeo involucrados).}.i.4e3
- Los enteros de 0 a 4000, excluyendo los puntos finales.=:
. J le permite tener una lista encuadrada de nombres en el LHS, como una forma de asignación múltiple calculada, por lo que esto funciona bien.Ahora el espacio de nombres J está lleno de variables que representan números romanos.
* Necesito que el número 2933774030998 se lea más tarde en la base 3. Sucede que puedo expresarlo en la base 79 usando dígitos no mayores que 30, lo cual es bueno porque J solo puede entender dígitos hasta 35 (0-9 y luego Arizona). Esto ahorra 3 caracteres sobre el decimal.
fuente
Pitón
La idea es simple como las otras respuestas. Pero solo para ser ordenado y no contaminar el espacio de nombres global, se utiliza un administrador de contexto. Esto también impone la restricción, que necesita declarar de antemano, la extensión del número romano que planea usar.
Nota Solo para que sea simple y no para reinventar la rueda, he utilizado el paquete romano de pitón
Implementación
Manifestación
fuente
Pitón
Esta es posiblemente la solución más simple usando Python:
fuente
globals()[var] = value
queexec()
.re
utilizando la evaluación de la función de tiempo de compilación de D
fuente
APL (Dyalog APL) , 77 bytes
Solicita la longitud máxima del número romano y define todas las variables.
t←
t consigue'IVXLCDM',
Caracteres romanos seguidos de⊂
un cerrado⍬
lista vacíat[
...]
índice t con ...⍉
la transpuesta (para obtener el orden correcto)8⊥⍣¯1
ancho apropiado base-ocho representación de⍳
los primeros n índices, donde n es¯1+
uno menos que8*⎕
ocho a la potencia de entrada numérica,/
aplanar filas (cada representación){
...}¨
aplique la siguiente función anónima en cada representación ...(
...)[t⍳⍵]
correspondiente a las posiciones de los elementos del argumento en t , seleccione entre ...∊
el alistado1 5∘ר
una y cinco veces cada uno de10*
diez al poder de⍳4
cero a tres0,⍨
agregar cero2(…)/
en cada ventana deslizante de longitud dos, aplique el siguiente tren de funciones anónimo ...⊣×
los tiempos de discusión de la izquierda¯1*
uno negativo al poder de<
si el argumento izquierdo es menor que el argumento derecho+/
suma⍵'←',
anteponer el argumento (el número romano) y una flecha de asignación⍕
formato (para aplanar y convertir el número a texto)⍎
ejecutar eso (realiza la asignación fuera de la función anónima)Pruébalo en línea! (usando max-length 5)
fuente
PHP
Hay varias reglas para números romanos válidos
Escriba el mayor valor antes de los valores más bajos.
Restar solo
[I,X,C]
antes de los siguientes 2 valores mayoresReste doble
[I,X,C]
antes de los siguientes 2 valores mayoresRestar doble
[I,X,C]
antes de los valores mayoresCombina 4 + 5
Versión en línea
Paso 1 Crea las reglas
es la salida JSON para todos los números romanos válidos
Paso 2 Haga listas para todas las reglas hasta 3999
Paso 3 Crear constantes
Combina todas las listas y define constantes
Salida
En el ejemplo, dos versiones válidas del número 8
fuente
Rebol
Ejemplo
Salida:
Descargo de responsabilidad: estoy seguro de que hay otras formas (¡y probablemente mejores!) De hacerlo también en Rebol.
PD. Mi
roman-to-integer
función es una transcripción del bonito algoritmo Ruby de histocrat para convertir la cadena de números romanos en un número. Volvió con gracias! +1fuente
Lua
Esto afecta la metatabla de la tabla global, dándole una nueva función de índice. Cuando se solicita una variable global que solo contiene números romanos, por ejemplo
XVII
, la analiza.Fácil de probar
Pruébalo en línea!
fuente
VBA, 204 bytes
Una subrutina declarada que no toma ninguna entrada y, cuando se ejecuta, crea la
public
ly accesibleEnum
,R
que contiene todos los valores de número romano. Estos valores se pueden usar directamente, sin hacer referencia a Enum.Enum hold valores del 1 al 3999.
Nota: Los terminales
"
s en las líneas 3 y 7 se incluyen solo para resaltar la sintaxis y no contribuyen al recuento de bytesNo golfista y explicado
fuente