language-agnostic code-golf rosetta-stone roman-numerals

language agnostic - Code Golf Año Nuevo Edition-Entero a Numeral Romano



language-agnostic code-golf (30)

Java: 286 caracteres significativos

public class R { String[]x="M,CM,D,C,XC,L,X,IX,V,I".split(","); int[]n={1000,900,500,100,90,50,10,9,5,1}; String p(String s,int d,int i){return 10<=i?s:n[i]<=d?p(s+x[i],d-n[i],i):p(s,d,i+1);} public static void main(String[] a) { System.out.println(new R().p("",Integer.parseInt(a[0]),0)); } }

Por "caracteres significativos" me refiero a los caracteres de impresión y los espacios requeridos (por ejemplo, entre el tipo y el argumento), pero no el espacio en blanco cosmético puro (líneas nuevas e indentación).

Escriba un programa que tome un solo argumento de línea de comando N e imprima el número romano correspondiente.

Por ejemplo, N = 2009 debería imprimir MMIX.

Digamos que esto debería funcionar para 0 <N <3000.

(Me divertí jugando mi primera ronda de golf de código con la edición de Navidad , y pensé que esto podría encajar para el Año Nuevo. Busqué en Google para ver si esto ha aparecido antes en otros lugares y parece que no, pero avíseme si esto es muy difícil o demasiado fácil o si las reglas necesitan cambios).

¡Feliz MMIX!


Lucio

60 caracteres, válido de 0 a 10000:

int main (int c, array a) { write(String.int2roman((int)a[1])); }


Idioma: C, Número de caracteres: 174

#define R(s,v)for(;n>=v;n-=v)printf(#s); main(int n,char**a){n=atoi(a[1]);R(M,1000)R(CM,900)R(D,500)R(CD,400)R(C,100)R(XC,90)R(L,50)R(XL,40)R(X,10)R(IX,9)R(V,5)R(IV,4)R(I,1)}


Aquí hay una solución C en 252 caracteres significativos. Válido desde 0 <= i <4000. Mayormente escribí esto porque muchas soluciones incluyen IV y IX en puntos de matriz. Descodificarlo: t es nuestro buffer temporal que rellenamos nuevamente para que no tengamos que revertirlo en la salida. El buffer pasado debe ser de al menos 16 caracteres (para 3888 -> MMMDCCCLXXXVIII).

char* i2r(int i, char* r) { char t[20]; char* o=t+19;*o=0; char* s="IVXLCDMM"; for (char*p=s+1;*p&&i;p+=2) { int x=i%10; if (x==9) {*--o=p[1];*--o=p[-1];} else if (x==4) {*--o=*p;*--o=p[-1];} else { for(;x&&x!=5;--x)*--o=p[-1]; if(x)*--o=*p; } i/=10; } return strcpy(r,o); }

Y siempre me olvido de poner el principal encendido. Tanto para 252 caracteres:

#include <stdio.h> #include <string.h> #include <stdlib.h> void main(int a,char**v){ char buf[16]; printf("%s/n",i2r(atoi(v[1]))); }


Ceceo común (SBCL). 63 caracteres contados por "wc -c".

(format t "~@R~%" (parse-integer (elt *posix-argv* 1))) (quit)

Esto solo funciona para números hasta 3999.


Delphi (o Pascal, no hay nada específico de Delphi aquí):

Function ToRoman(N : Integer) : String; Const V : Array [1..13] of Word = (1000,900,500,400,100,90,50,40,10.9,5,4,1); T : Array [1..13] of String = (''M'',''CM'',''D'',''CD'',''C'',''XC'',''L'',''XL'',''X'',''IX'',''V'',''I''); Var I : Word; Begin I := 1; Repeat While N < V[I] do Inc(I); Result := Result + T[I]; N := N - V[I]; Until N = 0; End;

¿Cómo va cada uno a contar el personaje? (Cuento 8 espacios esenciales, el resto son simplemente para formatear).


Desde un lenguaje vagamente parecido a C llamado LPC (precursor de Pike):

string roman_numeral(int val) { check_argument(1, val, #''intp); unless(val) return "N"; string out = ""; if(val < 0) { out += "-"; val = -val; } if(val >= 1000) { out += "M" * (val / 1000); val %= 1000; } if(val >= 100) { int part = val / 100; switch(part) { case 9 : out += "CM"; break; case 6 .. 8 : out += "D" + ("C" * (part - 5)); break; case 5 : out += "D"; break; case 4 : out += "CD"; break; default : out += "C" * part; break; } val %= 100; } if(val >= 10) { int part = val / 10; switch(part) { case 9 : out += "XC"; break; case 6 .. 8 : out += "L" + ("X" * (part - 5)); break; case 5 : out += "L"; break; case 4 : out += "XL"; break; default : out += "X" * part; break; } val %= 10; } switch(val) { case 9 : out += "IX"; break; case 6 .. 8 : out += "V" + ("I" * (val - 5)); break; case 5 : out += "V"; break; case 4 : out += "IV"; break; default : out += "I" * val; break; } return out; }


En Python, tomado de ActiveState (créditos: Paul Winkler) y comprimido un poco:

def int2roman(n): if not 0 < n < 4000: raise ValueError ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1) nums = (''M'', ''CM'', ''D'', ''CD'',''C'', ''XC'',''L'',''XL'',''X'',''IX'',''V'',''IV'',''I'') result = "" for i in range(len(ints)): count = int(n / ints[i]) result += nums[i] * count n -= ints[i] * count return result


Perl, 145 golpes (si quitas todas las líneas nuevas, que son opcionales), válido para 1..3999:

%t=qw(1000 M 900 CM 500 D 400 CD 100 C 90 XC 50 L 40 XL 10 X 9 IX 5 V 4 IV 1 I); $d=pop; for(sort{$b<=>$a}keys%t){$r.=$t{$_}x($d/$_);$d%=$_} print$r

Algunos dirían que podría usar say , pero no tengo una versión de Perl habilitada aquí. Siéntase libre de restar 2 del recuento de trazos si usa say works. :-)

Para los programadores que no pertenecen a Perl, este programa explota varias características útiles de Perl:

  1. Los hashes se construyen a partir de listas de igual longitud.
  2. Las listas de cadenas se pueden especificar en una sintaxis compacta, usando qw .
  3. Las cadenas pueden forzar automáticamente en enteros, como se usa en el operador de comparación <=> al ordenar las claves.
  4. Hay un operador x que hace copias de cadenas / listas. Desafortunadamente para jugar golf aquí, x tiene la misma precedencia que / ; si / fueran más altos, los corchetes también serían opcionales.

Perl, 19 golpes. Garantizado para trabajar por valores entre 1 y 12.

sub r{chr 8543+pop}


Python, 173 bytes.

r=lambda n:o[n]if n<10 else''''.join(dict(zip(''ivxlc'',''xlcdm''))[c]for c in r(n//10))+o[n%10] o='' i ii iii iv v vi vii viii ix''.split('' '') import sys print r(int(sys.argv[1]))

(Primero vi este algoritmo en Algoritmos de Gimpel en Snobol4 ; Snobol lo expresó de manera más elegante).


Real simple: pasa la consulta a Google y pantallas descifra la respuesta. Siguiente. :pag

Por cierto, ¿no debería ser esta una wiki de la comunidad?


Idioma: cc (a través de shell) Número de caracteres: 122

EDITAR: q es equivalente a 2Q

dc -e ''[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]?1000[szsz2Q]sq[~Sa[d0!<qrdPr1-lbx]dsbxLarz3<c]dscx10P'' <<<$1

EDITAR: dos caracteres más mediante la optimización de las manipulaciones de la pila de bucle principal

dc -e ''[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]?1000[szsz2Q]sq[~Sa[d0!<qrdPr1-lbx]dsbxLarz3<c]dscx10P'' <<<$1

EDITAR: guardar 2 caracteres

dc -e ''[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]1000?[sz2Q]sq[r~r[d0!<qSardPrLa1-lbx]dsbxrszz2<c]dscx10P'' <<<$1

Versión previa:

dc -e ''[I]1[IV]4[V]5[IX]9[X]10[XL]40[L]50[XC]90[C]100[CD]400[D]500[CM]900[M]1000?[sz2Q]sq[r~r[d0!<qSaSadPLaLa1-lbx]dsbxrszz2<c]dscx10P'' <<<$1


VB: 193 caracteres

Function c(ByVal a) Dim v() = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} Dim s = "" For i = 0 To 12 While a >= v(i) a -= v(i) s += "M|CM|D|CD|C|XC|L|XL|X|IX|V|IV|I".Split("|")(i) End While Next Return s End Function


Idioma: JavaScript .

129 caracteres sin el formato agregado

El siguiente código es el resultado del cuestionario de codificación que tuvo lugar en el pl.comp.lang.javascript noticias pl.comp.lang.javascript hace varios años. No soy el autor del código.

function rome(N,s,b,a,o){ for(s=b='''',a=5;N;b++,a^=7)for(o=N%a,N=N/a^0;o--;) s=''IVXLCDM''.charAt(o>2?b+N-(N&=~1)+(o=1):b)+s;return s }

Original post por Elus


Railo CFML - 53 caracteres, 46 sin espacio en blanco ...

<cfoutput> #NumberFormat( N , ''roman'' )# </cfoutput>


O, para otros motores CF, no estoy seguro si estos son los más cortos, pero lo harán por ahora ...

CFML - 350..453 caracteres:

<cffunction name="RomanNumberFormat"> <cfset var D = ListToArray(''M,CM,D,C,XC,L,X,IX,V,IV,I'') /> <cfset var I = [1000,900,500,100,90,50,10,9,5,4,1] /> <cfset var R = '''' /> <cfset var x = 1 /> <cfset var A = Arguments[1] /> <cfloop condition="A GT 0"> <cfloop condition="A GTE I[x]"> <cfset R &= D[x] /> <cfset A -= I[x] /> </cfloop> <cfset x++ /> </cfloop> <cfreturn R /> </cffunction> <cfoutput> #RomanNumberFormat(N)# </cfoutput>


CFScript - 219..323 caracteres:

<cfscript> function RomanNumberFormat(A) { var D = ListToArray(''M,CM,D,C,XC,L,X,IX,V,IV,I''); var I = [1000,900,500,100,90,50,10,9,5,4,1]; var R = ''''; var x = 1; while ( A > 0 ) { while( A >= I[x] ) { R &= D[x]; A -= I[x]; } x++; } return R; } WriteOutput( RomanNumberFormat(N) ); </cfscript>


Ruby, 136 caracteres

n = $*[0].to_i for k,v in [1e3,900,500,400,100,90,50,40,10,9,5,4,1].zip %w{M CM D CD C XC L XL X IX V IV I} until n < k n -= k print v end end


Perl: 69 golpes (¡cuéntalos!)

Sesenta y nueve golpes, incluido el llamado perl en primer lugar:

$ perl -ple''s!.!($#.=5x$&*8%29628)=~y$IVCXL4620-8$XLMCDIXV$d!eg;last}{'' 3484 MMMCDLXXXIV

  • Lee una sola línea, escribe una sola línea.
  • Funciona desde 0 hasta 3999, inclusive. (Imprime cadena vacía para 0.)
  • En las competiciones de golf de Perl, generalmente se puntúa como 62 golpes = 58 para el código + 4 para los interruptores.
  • Por qué, sí, esos son brackets no coincidentes. Gracias por preguntar. =)

Créditos: originalmente debido a Ton Hospel . El truco que involucra los aparatos no coincidentes es de rev.pl en este post (que, por cierto, es ingenioso ).


En C #, como método de extensión para Int32 :

public static class Int32Extension { public static string ToRomanNumeral(this int number) { Dictionary<int, string> lookup = new Dictionary<int, string>() { { 1000000, "M_" }, { 900000, "C_D_" }, { 500000, "D_" }, { 400000, "C_D_" }, { 100000, "C_" }, { 90000, "X_C_" }, { 50000, "L_" }, { 40000, "X_L_" }, { 10000, "X_" }, { 9000, "MX_"}, { 5000, "V_" }, { 4000, "MV_" }, { 1000, "M" }, { 900, "CM" }, { 500, "D" }, { 400, "CD" }, { 100,"C" }, { 90, "XC" }, { 50, "L" }, { 40, "XL" }, { 10, "X" }, { 9, "IX" }, { 5, "V" }, { 4, "IV" }, { 1, "I" } }; StringBuilder answer = new StringBuilder(); foreach (int key in lookup.Keys.OrderBy(k => -1 * k)) { while (number >= key) { number -= key; answer.Append(lookup[key]); } } return answer.ToString(); } }

Los caracteres de subrayado deben ser sobreimpresiones encima de la letra respectiva para ser verdadero Numeral Romano.


No soy experto en Haskell, y esto es demasiado tiempo para ser un ganador, pero esta es una solución que escribí hace un tiempo para resolver Euler # 89.

toRoman 0 = "" toRoman 1 = "I" toRoman 2 = "II" toRoman 3 = "III" toRoman 4 = "IV" toRoman n | n >= 1000 = repeatRoman ''M'' 1000 | n >= 900 = subtractRoman "CM" 900 | n >= 500 = subtractRoman "D" 500 | n >= 400 = subtractRoman "CD" 400 | n >= 100 = repeatRoman ''C'' 100 | n >= 90 = subtractRoman "XC" 90 | n >= 50 = subtractRoman "L" 50 | n >= 40 = subtractRoman "XL" 40 | n >= 10 = repeatRoman ''X'' 10 | n >= 9 = subtractRoman "IX" 9 | n >= 5 = subtractRoman "V" 5 | otherwise = error "Hunh?" where repeatRoman c n'' = (take (n `div` n'') (repeat c)) ++ (toRoman $ n `mod` n'') subtractRoman s n'' = s ++ (toRoman $ n - n'')


En C # (ejecutándose en .NET 4 RC), con 335 caracteres (si elimina el formato extraño).

using System; using System.Linq; class C { static void Main() { Console.WriteLine( Console.ReadLine() .PadLeft(4,''0'') .Select(d=>d-''0'') .Zip(new[]{" M","MDC","CLX","XVI"},(x,y)=>new{x,y}) .Aggregate("",(r,t)=>r+ new string(t.y[2],t.x%5/4)+ new string(t.y[0],t.x%5/4*t.x/5)+ new string(t.y[1],Math.Abs(t.x%5/4-t.x/5))+ new string(t.y[2],t.x%5%4))); } }

Sé que no supera la mejor respuesta de C # actual (182 caracteres), pero este es solo un gran LINQ one-liner. Una vez que vi un raytracer escrito como una sola consulta LINQ , comencé a abordar golf de código desde esta perspectiva.

Como este enfoque es funcional, estoy trabajando en una versión de Haskell del mismo algoritmo (seguramente será más corta).


J, 20 caracteres!

''MDCLXVI''#~(7$5 2)#:

Uso:

''MDCLXVI''#~(7$5 2)#: 2009 MMVIIII

De acuerdo, no hace la resta correctamente, ¡pero es genial!

Explicación;

(7$5 2)

Esto toma el argumento correcto (la lista 5 2 ) y lo convierte en una lista de tamaño 7, concretamente 5 2 5 2 5 2 5 .

(7$5 2)#: 2009

Esto hace la operación "anti-base", básicamente haciendo operaciones iterativas de div y mod, devolviendo la lista 2 0 0 0 0 0 1 4 .

Entonces #~ usa la lista anterior como un conteo para sacar los caracteres correspondientes de ''MDCLXVI'' .


C #: 179 caracteres (sin incluir espacios / pestañas)

static string c(int a) { int[] v = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; var s = ""; for ( var i = 0; i < 13; i++ ) while (a >= v[i]) { a -= v[i]; s += "M CM D CD C XC L XL X IX V IV I".Split()[i]; } return s; }


Una versión simple de Haskell, que aún mantiene la claridad. 205 caracteres, incluido el espacio en blanco.

l = ["M","CM","L","CD","C","XC","L","XL","X","IX","V","IV","I"] v = [1000,900,500,400,100,90,50,40,10,9,5,4,1] roman n i | n == 0 = "" | n >= v!!i = l!!i ++ roman (n-v!!i) i | otherwise = roman n (i+1)


Caracteres de Excel 8 (sin incluir el número):

= ROMANO (N)

Funciona hasta 3000.

Lengua en la mejilla


Idioma: Erlang, Número de Char: 222

EDIT2: el preprocesador de Erlang permite algún tipo de macros desequilibradas, por lo que esta versión tiene 9 caracteres más.

-module(n2). -export([y/1]). -define(D(V,S),n(N)when N>=V->[??S|n(N-V)];). y(N)->io:format(n(N)). ?D(1000,M)?D(900,CM)?D(500,D)?D(400,CD)?D(100,C)?D(90,XC)?D(50,L)?D(40,XL)?D(10,X)?D(9,IX)?D(5,V)?D(4,IV)?D(1,I)n(0)->[10].

EDITAR: versión más corta inspirada en la versión de Darius (231 caracteres)

-module(n). -export([y/1]). y(N)->io:format([n(N),10]). n(N)when N>9->[Y||C<-n(N div 10),{K,Y}<-lists:zip("IVXLC","XLCDM"),K==C]++o(N rem 10);n(N)->o(N). o(N)->lists:nth(N+1,[[]|string:tokens("I II III IV V VI VII VIII IX"," ")]).

Es menos legible pero ahorra 2 caracteres (233 caracteres).

-module(n). -export([y/1]). -define(D(V,S),n(N)when N>=V->[??S|n(N-V)]). y(N)->io:format(n(N)). ?D(1000,M);?D(900,CM);?D(500,D);?D(400,CD);?D(100,C);?D(90,XC);?D(50,L);?D(40,XL);?D(10,X);?D(9,IX);?D(5,V);?D(4,IV);?D(1,I);n(0)->[10].

Versión de línea de comando:

-module(n). -export([y/1]). -define(D(V,S),n(N)when N>=V->[??S|n(N-V)]). y([N])->io:format(n(list_to_integer(N))),init:stop(). ?D(1000,M);?D(900,CM);?D(500,D);?D(400,CD);?D(100,C);?D(90,XC);?D(50,L);?D(40,XL);?D(10,X);?D(9,IX);?D(5,V);?D(4,IV);?D(1,I);n(0)->[10].

Invocación:

$ erl -noshell -noinput -run n y 2009 MMIX

EDITAR: Guardé 17 caracteres usando la expansión de macro literal.


Versión Haskell de mi respuesta C # / LINQ , 234 caracteres:

main=putStrLn.foldr(/(y,x)s->concat[s,r(a x)(y!!2),r(a x*div x 5)(y!!0),r(abs(a x-div x 5))(y!!1),r(mod(mod x 5)4)(y!!2)])"".zip["XVI","CLX","MDC"," M"].map(read.(:[])).take 4.(++"000").reverse=<<getLine r=replicate a x=div(mod x 5)4


Idioma: C, Número de caracteres: 195

Basada en gran medida en la solución C de me.yahoo.com/joe_mucchielle :

char t[99],*o=t+99,*s="IVXLCDMM",*p,x;n(v){*--o=p[v];}main(int i,int**v){i=atoi(v[1]);*o=0; for(p=s+1;*p&&i;p+=2){x=i%10;if(x%5==4)n(x==9),n(-1);else{for(;x%5;--x)n(-1);if(x)n(0);}i/=10;}puts(o);}


Python, 190 bytes . Basado en un fragmento de ActiveState , a través de Federico .

Algunas optimizaciones pequeñas: eliminación de llamadas superfluas de int (), división de cadena para obtener matriz, eliminación de espacios en blanco, ...

import sys n=int(sys.argv[1]) N=(1000,900,500,400,100,90,50,40,10,9,5,4,1) r="" for i in range(len(N)): c=n/N[i] r+=''M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I''.split('','')[i]*c n-=N[i]*c print r

EDITAR : superfluo, no espurio, y eliminar el control de rango - ¡gracias a Chris y dreeves ! Robó la idea de usar la matriz de símbolos en línea de balabaster .


Perl 5.10

perl -nE''@l=qw{1 I 4 IV 5 V 9 IX 10 X 40 XL 50 L 90 XC 100 C 400 CD 500 D 900 CM 1000 M}; $o="";while(@l){$o.=pop(@l)x($_/($c=pop @l));$_%=$c;}say$o''

Ingresas una línea, te da el equivalente en números romanos. Esta primera versión incluso te permite ingresar a más de una línea.

Aquí hay una versión más corta que solo funciona para una línea e ignora los casos extremos. entonces 4 convierte en IIII lugar de IV .

perl -nE''@l=qw{1 I 5 V 10 X 50 L 100 C 500 D 1000 M}; while(@l){$o.=pop(@l)x($_/($c=pop @l));$_%=$c;}say$o''

Así es como se vería la primera versión como una secuencia de comandos de Perl.

use 5.010; while(<>){ @l=qw{1 I 4 IV 5 V 9 IX 10 X 40 XL 50 L 90 XC 100 C 400 CD 500 D 900 CM 1000 M}; $o=""; while(@l){ $o .= pop(@l) x ($_/($c=pop @l)); # $l = pop @l; # $c = pop @l; # $o .= $l x ($_/$c); $_ %= $c; } say $o; }