Escriba un programa que cuente del 1 al 100 en números romanos e imprima estos números por salida estándar. Cada uno de los números debe estar separado por espacios.
No puede utilizar ninguna función integrada para transformar a números romanos ni una aplicación externa o biblioteca para hacerlo.
El resultado deseado es
I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII XXXIX XL XLI XLII XLIII XLIV XLV XLVI XLVII XLVIII XLIX L LI LII LIII LIV LV LVI LVII LVIII LIX LX LXI LXII LXIII LXIV LXV LXVI LXVII LXVIII LXIX LXX LXXI LXXII LXXIII LXXIV LXXV LXXVI LXXVII LXXVIII LXXIX LXXX LXXXI LXXXII LXXXIII LXXXIV LXXXV LXXXVI LXXXVII LXXXVIII LXXXIX XC XCI XCII XCIII XCIV XCV XCVI XCVII XCVIII XCIX C
Como es un desafío de código de golf, gana el código más corto .
Respuestas:
Perl 69 bytes
Funciona a modo de fórmula mágica. La expresión
"32e$&"%72726
transforma cada dígito de la siguiente manera:0⇒32, 1⇒320, 2⇒3200, 3⇒32000, 4⇒29096, 5⇒56, 6⇒560, 7⇒5600, 8⇒56000, 9⇒50918
Después de aplicar la traducción
y/016/IXV/
, tenemos esto en su lugar:0⇒32, 1⇒32 I , 2⇒32 II , 3⇒32 III , 4⇒29 I 9 V , 5⇒5 V , 6⇒5 VI , 7⇒5 VII , 8⇒5 VIII , 9⇒5 I 9 X 8
El resto de los dígitos (
2-57-9
) se eliminan. Tenga en cuenta que esto podría mejorarse en un byte mediante el uso de una fórmula que se traduce en012
lugar de016
, simplificando/XVI60-9/
a/XVI0-9/
. No pude encontrar uno, pero quizás tengas mejor suerte.Una vez que un dígito se ha transformado de esta manera, el proceso se repite para el siguiente dígito, agregando el resultado y traduciendo los
XVI
s anteriores alCLX
mismo tiempo que ocurre la traducción para el nuevo dígito.Actualización La
búsqueda exhaustiva no reveló nada más corto. Sin embargo, encontré una solución alternativa de 69 bytes:
Este usa una
0-2
sustitución paraIXV
, pero tiene un módulo que es un dígito más largo.Actualización:
6665 bytesEsta versión es notablemente diferente, por lo que probablemente debería decir algunas palabras al respecto. ¡La fórmula que usa es en realidad un byte más!
Incapaz de acortar la fórmula más de lo que es, decidí jugar al golf con lo que tenía. No pasó mucho tiempo hasta que recordé a mi viejo amigo
$\
. Cuandoprint
se emite una declaración,$\
se agrega automáticamente al final de la salida. Pude deshacerme de la$a[$_]
construcción incómoda para una mejora de dos bytes:Mucho mejor, pero eso
$\=!print$"
todavía se veía un poco detallado. Entonces recordé una fórmula alternativa de igual longitud que había encontrado que no contenía el número3
en ninguna de sus transformaciones de dígitos. Por lo tanto, debería ser posible usar$\=2+print
en su lugar, y sustituir el resultado3
con un espacio:También 67 bytes, debido al espacio en blanco necesario entre
print
yfor
.Pero, si hubiera una fórmula que no utilizara un
1
lugar, se$\=2+print
convierte$\=print
en otros dos bytes de ahorro. Incluso si fuera un byte más, aún sería una mejora.Como resultado, dicha fórmula existe, pero es un byte más larga que la original, lo que resulta en una puntuación final de 65 bytes :
Metodología
Se hizo la pregunta de cómo se puede encontrar una fórmula de este tipo. En general, encontrar una fórmula mágica para generalizar cualquier conjunto de datos es una cuestión de probabilidad. Es decir, desea elegir una forma que sea lo más probable posible para producir algo similar al resultado deseado.
Examing los primeros números romanos:
Hay cierta regularidad para ser visto. Específicamente, de 0-3 y luego nuevamente de 5-8 , cada término sucesivo aumenta en longitud en un número. Si quisiéramos crear un mapeo de dígitos a números, querríamos tener una expresión que también aumente su longitud en un dígito por cada término sucesivo. Una opción lógica es k • 10 d donde d es el dígito correspondiente yk es cualquier constante entera.
Esto funciona para 0-3 , pero 4 necesita romper el patrón. Lo que podemos hacer aquí es tachuela en un módulo:
k • 10 d % m , donde m es un lugar entre k • 10 3 y k • 10 4 . Esto dejará el rango 0-3 intacto y modificará 4 de manera tal que no contendrá cuatro
I
s. Si además restringimos nuestro algoritmo de búsqueda de modo que el residuo modular de 5 , llamémoslo j , sea menor que m / 1000 , esto asegurará que también tengamos regularidad de 5-8 . El resultado es algo como esto:Como puede ver, si reemplazamos
0
conI
, ¡ 0-3 y 5-8 están garantizados para mapearse correctamente! Sin embargo, los valores para 4 y 9 deben ser forzados. Específicamente, 4 debe contener uno0
y unoj
(en ese orden), y 9 debe contener uno0
, seguido de otro dígito que no aparece en ningún otro lugar. Ciertamente, hay una serie de otras fórmulas, que por casualidad podrían producir el resultado deseado. Algunos de ellos incluso pueden ser más cortos. Pero no creo que haya ninguno que tenga tanto éxito como este.También experimenté con múltiples reemplazos para
I
y / oV
con algún éxito. Pero, por desgracia, nada más corto que lo que ya tenía. Aquí hay una lista de las soluciones más cortas que encontré (la cantidad de soluciones de 1-2 bytes más pesadas son demasiadas para enumerarlas):fuente
HTML + JavaScript + CSS (137)
HTML (9)
JavaScript (101)
CSS (27)
Salida
...
Demo en JSBin
fuente
document.write('<ol>'+"<li style='list-style:upper-roman'/>".repeat(100)+'</ol>')
(ES6)document.write("<li style='list-style:upper-roman'/>".repeat(100))
Python 116
mejor código de golf de la respuesta de Scleaver:
fuente
Pitón, 139
fuente
C,
177160147 caracteresHay soluciones más cortas, pero ninguna en C, así que aquí está mi intento.
Nueva solución, completamente diferente de la anterior:
Solución anterior (160 caracteres):
Lógica:
1.
f
imprime un número del 1 al 10.c
son los dígitos utilizados, que pueden serIVX
oXLC
. Llamado una vez por las decenas una vez por las.2. If
n%5==0
: no imprime nada oc[n/5]
cuál esI
oV
(oL
oC
).3. Si
n%4==4
-4
o9
- imprimeI
(oX
), porn+1
.4. If
n>4
- imprimir5
(es decir,V
oL
) entoncesn-5
.5. If
n<4
- imprimeI
entoncesn-1
(es decir,n
vecesI
).fuente
f(c,n){printf("%.*s",n%5>3?2:n%5+n/5,"XLXXXCIVIIIX "+c+(n%5>3?n%4*4:2-n/5));}main(i){for(;i<100;f(12,4))f(0,i/10),f(6,i++%10);puts("C");}
JavaScript, 123
Inspirado por una versión más larga que encontré en un grupo de noticias polaco (al menos, Chrome pensó que era polaco).
fuente
Q (
8180)2do corte:
1er corte:
fuente
Pitón, 168
Explicación
Usando estos valores, tome el valor más grande no mayor que n y reste de n. Repita hasta que n sea 0.
fuente
r=lambda n,l,v:n and(n<v[0]and r(n,l[1:],v[1:])or l[0]+r(n-v[0],l,v))or""
Guarda dos personajes. De lo contrario, muy agradable.Rubí 1.9,
140132Esto literalmente cuenta del 1 al 100 en números romanos. Comienza con una cadena en blanco, luego se repite agregando "I" y luego aplica repetidamente una serie de reglas de sustitución, agregando efectivamente 1.
Editar: se agregó el número de versión, ya que
?I
solo funciona en 1.9, y se usaron los cambios de @ Howard para recortar algunos caracteres.fuente
r while
->0while
,r.sub!(*q)
->r.sub! *q
. También puede arrastrar la impresión dentro del bucle y usarla en100.times{...}
lugar de la declaración del mapa.(%w[IIII VIV XXXX LXL]<</(.)((?!\1)[^I])\1/).zip(%w(IV IX XL XC)<<'\2')
ahorra 7 caracteres.Ruby 112 caracteres
Básicamente usando el
to_roman
método explicado aquí , pero usando una matriz comprimida por brevedad.fuente
Mathematica
159 150142Solución incorporada :
IntegerString
38 caracteresfuente
perl 205
Golfizado:
fuente
MUMPS 184
Mismo algoritmo que @cardboard_box, de quien tomé la explicación literalmente:
Explicación
Usando estos valores, tome el valor más grande no mayor que n y reste de n. Repita hasta que n sea 0.
fuente
R , 85 bytes
Pruébalo en línea!
Utiliza la
utils
variable de paquete aleatorio.romans
para obtener los valores de los números romanos, pero realiza la conversión por sí mismo; el enfoque integrado sería de 20 bytes:cat(as.roman(1:100))
fuente
cat(paste(as.roman(1:100)))
o simplementeas.roman(1:100)
. Extraño.cat
indican que realiza menos conversión queprint
y solo funciona enatomic
vectores, ¡eso explica esto!APL 128
Probé una solución de indexación en APL:
Puede ser 4 bytes más corto en el índice de origen 0 en lugar de 1, pero el espacio real es la generación de la matriz de índice a través de:
¡Hasta ahora no he podido generar los índices sobre la marcha!
fuente
LaTeX (138)
fuente
Python, 125
fuente
PHP,
3837 bytes<ol type=I><?=str_repeat("<li>",100);
-1 byte gracias a @manatwork
La misma idea que la respuesta de Patrick , pero en un lenguaje más compacto. Beats Mathematica !
Pruébalo en línea!
fuente
;
, luego no es necesario?>
.VBA (Excel), 245 bytes
Función creada para repetición y reemplazo - 91 bytes
Function s(a,b):s=String(a,b):End Function Function b(x,y,z):b=Replace(x,y,z):End Function
usando la ventana inmediata ( 154 bytes )
p="I":for x=1to 100:?b(b(b(b(b(b(b(b(s(x,p),s(100,p),"C"),s(90,p),"XC"),s(50,p),"L"),s(40,p),"XL"),s(10,p),"X"),s(9,p),"IX"),s(5,p),"V"),s(4,p),"IV"):next
fuente
Java (OpenJDK 8) , 152 bytes
Pruébalo en línea!
Explicación:
fuente
TeX, 354 bytes
Alguna explicación: TeX proporciona un comando incorporado
\romannumeral
para convertir números a números romanos. Como la pregunta no permite usar funciones integradas, el código anterior es una versión desarrollada del mismo algoritmo que el compilador TeX original de Knuth usa para\romannumeral
(ver TeX: El Programa , § 69,print_roman_int
) re-implementado en TeX.Como quiere dejar la alegría de desconcertar cómo funciona este código para el lector, Knuth se niega a dar una explicación de esta parte del código. Así que haré lo mismo y solo daré una versión no modificada y ligeramente modificada, que está más cerca del original que el código anterior:
fuente