tesis sobre investigaciones language-agnostic code-golf rosetta-stone

language-agnostic - tesis - investigaciones sobre netflix



Code Golf: Cuatro es magia (30)

GolfScript - 101 96 93 92 91 90 94 86 bytes

90 → 94 : salida fija para múltiplos de 10.
94 → 86 : Código reestructurado. Usar base 100 para eliminar caracteres no imprimibles.
86 → 85 : Lanzamiento más corto a la cuerda.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "/". "1$4$4-}do;;;"magic."

El rompecabezas

Un pequeño acertijo que escuché mientras estaba en la escuela secundaria fue algo como esto ...

  • El que pregunta me pide que le dé un número;
  • Al escuchar el número, el interlocutor haría algún tipo de transformación repetidamente (por ejemplo, podría decir que diez es tres ) hasta llegar al número 4 (en ese punto terminaría con cuatro es mágico ).
  • Cualquier número parece ser transformable en cuatro eventualmente, sin importar qué.

El objetivo era tratar de descubrir la función de transformación y luego ser capaz de realizar este enigma de manera confiable.

La solución

La función de transformación en cualquier paso era

  • Toma el número en cuestión,
  • Cuente el número de letras en su representación de palabras en inglés, ignorando un guión o espacios o "y" (p. Ej., "Diez" tiene 3 letras, "treinta y cuatro" tiene 10 letras, "ciento cuarenta y tres" tiene 20 letras)
  • Devuelve ese número de letras.

Para todos los números que he querido probar, esto converge a 4. Como "cuatro" también tiene cuatro letras, aquí habría un ciclo infinito; en cambio, simplemente se lo denomina magia por convención para finalizar la secuencia.

El reto

Su desafío es crear un fragmento de código que lea un número del usuario y luego imprimir líneas que muestren la función de transformación aplicada repetidamente hasta que se alcance "cuatro es mágico".

Específicamente:

  1. Las soluciones deben ser programas completos en sí mismas. No pueden ser simplemente funciones que tienen en cuenta un factor numérico.
  2. La entrada debe leerse de la entrada estándar. (Tubería de "eco" o usando la redirección de entrada está bien ya que también va desde stdin)
  3. La entrada debe ser en forma numérica.
  4. Para cada aplicación de la función de transformación, se debe imprimir una línea: a is b. , donde a y b son formas numéricas de los números en la transformación.
  5. ¡Se requieren paradas completas (períodos)!
  6. La última línea debería decir, 4 is magic. .
  7. El código debería producir una salida correcta para todos los números del 0 al 99 .

Ejemplos:

> 4 4 is magic. > 12 12 is 6. 6 is 3. 3 is 5. 5 is 4. 4 is magic. > 42 42 is 8. 8 is 5. 5 is 4. 4 is magic. > 0 0 is 4. 4 is magic. > 99 99 is 10. 10 is 3. 3 is 5. 5 is 4. 4 is magic.

El ganador es el envío más corto por el recuento de caracteres del código fuente, que también es correcto .

PRIMA

También puede intentar escribir una versión del código que imprime los NOMBRES DE INGLÉS para los números con cada aplicación de la función de transformación. La entrada original sigue siendo numérica, pero las líneas de salida deben tener la forma de palabra del número.

(Doble bonificación para dibujar formas con tu código)

(EDIT) Algunas aclaraciones:

  1. Quiero que la palabra aparezca en ambos lados en todos los casos aplicables, por ejemplo, Nine is four. Four is magic. Nine is four. Four is magic.
  2. Aunque no me importan las mayúsculas. Y no me importa cómo separe los tokens de palabras, aunque deberían separarse: el ninety-nine está bien, el ninety nine ninety-nine está bien, el ninety nine no está bien.

Considero que se trata de una categoría separada para la competencia de bonificación en relación con el desafío, por lo que si opta por esto, no se preocupe porque su código sea más largo que la versión numérica.

Siéntase libre de enviar una solución para cada versión.


Haskell, 224 270 caracteres

o="43354435543668877988" x!i=read[x!!i] n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10 f x=zipWith(/a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"] main=readLn>>=mapM putStrLn.f

Y poco más legible -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8] tens = [0,0,6,6,5,5,5,7,6,6] n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10) f x = zipWith (/a b -> a ++ " is " ++ b ++ ".") l (tail l) where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"] main = readLn >>= mapM putStrLn . f


T-SQL, 413 451 499 caracteres

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN Declare @l char(50), @s char(50) Select @l=''0066555766'',@s=''03354435543668877987'' if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END GO CREATE proc M(@x int) as BEGIN WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,''is'',n,''.'' from r print ''4 is magic.''END

(No es que esté sugiriendo seriamente que harías esto ... realmente solo quería escribir un CTE)

Usar:

M 95

Devoluciones

p n ----------- ---- ----------- 95 is 10. 10 is 3. 3 is 5. 5 is 4. 4 is magic.


Windows PowerShell: 152 153 184 bytes

basado en la solución anterior, con más influencia de otras soluciones

$o="03354435543668877988" for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a "$a is $b."}''4 is magic.''


perl, 123 122 caracteres

Me acabo de dar cuenta de que no hay ningún requisito para enviar a STDOUT, por lo que se envía a STDERR y desactiva otro personaje.

@u=''0335443554366887798866555766''=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,"./n"until/g/

Y, una versión que devuelve números detallados:

279 278 276 280 caracteres

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~//w/g:magic,"./n"until/c/

Si bien cumple con las especificaciones, no está formateado al 100%. Devuelve un espacio extra después de que los números terminan en cero. La especificación dice:

"No me importa cómo separe los tokens de palabras, aunque deberían separarse"

Eso es un poco weaselly sin embargo. Una versión más correcta en

282 281 279 283 caracteres

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("/x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~//w/g:magic,"./n"until/c/


Perl - 130 chars

5.12.1 (130 chars) 121 123 132 136 140

# 1 2 3 4 5 6 7 8 9 100 11 12 13 14 #23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123 @u=''4335443554366887798866555766''=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until//D/


5.10.1 (134 chars) 125 127 136 140 144

# 1 2 3 4 5 6 7 8 9 100 11 12 13 14 #23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234 @u=''4335443554366887798866555766''=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"./n"until//D/


Change History:

20100714:2223 - reverted change at the attention of mobrule , but ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]) , which is the same # of chars, but I did it in case someone might see a way to improve it

20100714:0041 - split//,''...''''...''=~/./g
20100714:0025 - ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340 - while$_until//D/ + removed unnecessary parentheses
20100713:xxxx - $=<>;chop;$_=pop; - courtesy to mobrule

Note: I was tired of improving others'' answers in comments, so now I''m being greedy and can just add my changes here :) This is a split off from Platinum Azure ''s answer - credit in part to hobbs , mobrule , and Platinum Azure .


C #: 210 caracteres.

Squished:

using C=System.Console;class B{static void Main(){int x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}./n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

Expandido:

using C=System.Console; class B { static void Main() { int x=0,y=int.Parse(C.ReadLine()); while(x!=4) C.Write((x=y)+" is {0}./n", x==4? "magic": ""+(y= x==0? 4: "03354435543668877988"[x<20?x:x%10]+ "0066555766"[x/10]-96) ); } }

Trucos que utiliza este enfoque:

  • Cree una tabla de búsqueda para las longitudes de los nombres de los números en función de los dígitos que aparecen en el número.
  • Use la búsqueda de matriz de caracteres en una cadena y la aritmética de caracteres en lugar de una matriz numérica.
  • Utilice el alias de nombre de clase en la Console. corta Console. a C.
  • Use el operador condicional (ternario) ( ?: lugar de if/else .
  • Utilice el /n con el código de escape Write lugar de WriteLine
  • Use el hecho de que C # tiene un orden de evaluación definido para permitir asignaciones dentro de la llamada de función de Write
  • Utilice las expresiones de asignación para eliminar declaraciones adicionales, y por lo tanto llaves adicionales

C - con palabras numeradas

445 431 427 421 399 386 371 359 * 356 354 348 347 caracteres

Eso es. No creo que pueda hacer esto más corto.

Todas las nuevas líneas son para facilitar la lectura y se pueden eliminar:

i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P, fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,./n, 4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48); }main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18), (c%=10)&&putchar(45):0,c:37);P(36);}

A continuación, está unificado, pero aún es bastante difícil de leer. Vea a continuación una versión más legible.

i; P(x){ char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,./n,4RmagicS,zero,"; while(x--) if(*++p-44&&!x++) *p>95|*p<48?putchar(*p),++i:P(*p-48); } main(c){ for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35)) P(c? c>19? P(c/10+18), (c%=10)&& putchar(45) :0, c :37); P(36); }

Ampliado y comentado:

int count; /* type int is assumed in the minified version */ void print(int index){ /* the minified version assumes a return type of int, but it''s ignored */ /* see explanation of this string after code */ char *word = /* 1 - 9 */ ",one,two,three,four,five,six,sM,eight,nine," /* 10 - 19 */ "tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P," /* 20 - 90, by tens */ "twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q," /* lookup table */ "en,evL,thir,eL,tO,ty, is ,./n,4RmagicS,zero,"; while(index >= 0){ if(*word == '','') index--; else if(index == 0) /* we found the right word */ if(*word >= ''0'' && *word < ''a'') /* a compression marker */ print(*word - ''0''/*convert to a number*/); else{ putchar(*word); /* write the letter to the output */ ++count; } ++word; } } int main(int argc, char **argv){ /* see note about this after code */ scanf("%d", &argc); /* parse user input to an integer */ while(argc != 4){ count = 0; if(argc == 0) print(37/*index of "zero"*/); else{ if(argc > 19){ print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/); argc %= 10; /* get low digit */ if(argc != 0) /* we need a hyphen before the low digit */ putchar(''-''); } print(argc/* if 0, then nothing is printed or counted */); } argc = count; print(34/*" is "*/); print(argc); /* print count as word */ print(35/*"./n"*/); } print(36/*"four is magic./n"*/); }

Acerca de la cadena codificada cerca del comienzo

Los nombres de los números se comprimen usando un esquema muy simple. Las subcadenas usadas con frecuencia se reemplazan con índices de un carácter en la matriz de nombres. Se agrega una "tabla de búsqueda" de entradas de nombre adicionales al final para las subcadenas que no se utilizan en su totalidad en el primer conjunto. Las búsquedas son recursivas: las entradas pueden referirse a otras entradas.

Por ejemplo, el nombre comprimido para 11 es elM . La función print() emite los caracteres e y l (minúscula ''L'', no número ''1'') al pie de la letra, pero luego encuentra la M , por lo que se llama con el índice de la entrada 29 (ASCII ''M'' - ASCII ''0'') en la tabla de búsqueda. Esta cadena es evL , por lo que emite e y v , luego se llama de nuevo con el índice de la entrada 28 en la tabla de búsqueda, que es en , y se emite textualmente. Esto es útil porque en también se usa en eL para een (se usa después de eight en eighteen ), que se usa en tO para teen (se usa para cada otro nombre).

Este esquema resulta en una compresión bastante significativa de los nombres de los números, mientras que requiere solo una pequeña cantidad de código para descomprimir.

Las comas al principio y al final de la cadena de cuentas de la forma simplista que las subcadenas se encuentran dentro de esta cadena. Agregar dos caracteres aquí guarda más caracteres más tarde.

Sobre el abuso de main()

argv se ignora (y, por lo tanto, no se declara en la versión comprimida), el valor de argc se ignora, pero el almacenamiento se reutiliza para contener el número actual. Esto simplemente me ahorra tener que declarar una variable adicional.

Acerca de la falta de #include

Algunos se quejarán de que omitir #include <stdio.h> es una trampa. No es en absoluto. El dado es un programa C completamente legal que se compilará correctamente en cualquier compilador C que conozca (aunque con advertencias). Al carecer de prototipos para las funciones stdio, el compilador asumirá que son funciones cdecl que retornan a int , y confiará en que usted sepa qué argumentos aprobar. Los valores de retorno se ignoran en este programa, de todos modos, y todos son funciones cdecl (convención de llamadas "C"), y de hecho sabemos qué argumentos aprobar.

Salida

La salida es como se esperaba:

0 zero is four. four is magic.

1 one is three. three is five. five is four. four is magic.

4 four is magic.

20 twenty is six. six is three. three is five. five is four. four is magic.

21 twenty-one is nine. nine is four. four is magic.

* La versión anterior omitió la marca en dos partes de la especificación: no manejaba cero, y tomó entrada en la línea de comando en lugar de stdin. La manipulación de caracteres añadidos a ceros, pero el uso de stdin en lugar de argumentos de línea de comando, así como un par de otras optimizaciones guardaba el mismo número de caracteres, lo que daba como resultado un lavado.

Los requisitos se han cambiado para dejar en claro que la palabra numérica se debe imprimir en ambos lados de "es". Esta nueva versión cumple con ese requisito e implementa un par de optimizaciones más para (más de) cuenta para el tamaño adicional necesario.


C - sin palabras numéricas

180 175 * 172 167 caracteres

Todas las nuevas líneas son para facilitar la lectura y se pueden eliminar:

i;V(x){return"/3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c); c-4;)i=c,printf("%d is %d./n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts( "4 is magic.");}

Ligeramente no miniaturizado

i; V(x){return"/3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;} main(c){ for(scanf("%d",&c);c-4;) i=c, printf("%d is %d./n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4); puts("4 is magic."); }

* La versión anterior omitió la marca en dos partes de la especificación: no manejaba cero, y tomó entrada en la línea de comando en lugar de stdin. Manejando cero caracteres añadidos, pero usando stdin en lugar de args de línea de comando ahorrados aún más, lo que resulta en un ahorro neto.


C, 158 caracteres

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d./n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(originalmente basado en el código Python de Vlad, tomó prestado un truco de la solución C ++ de Tom Sirgedas para exprimir algunos caracteres más)

versión expandida:

main(n, c) { char *d = "03354435543668877988"; for (scanf("%d",&n); n-4; n = c) printf("%d is %d./n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10] : 4); puts("4 is magic."); }


Delphi: 329 caracteres

Versión de línea única:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A=''EDDFEEDFFEDGGIIHHJII'';B=''DGGFFFJGG'';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write(''> '');ReadLn(X);repeat Y:=Z(X);WriteLn(Format(''%d is %d.'',[X,Y]));X:=Y;until X=4;WriteLn(''4 is magic.'');end.

Formateado:

program P; {$APPTYPE CONSOLE} uses SysUtils; const S = 65; A = ''EDDFEEDFFEDGGIIHHJII''; B = ''DGGFFFJGG''; function Z(X:Byte):Byte; begin if X<20 then Z := Ord(A[X+1])-S else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10); end; var X,Y: Byte; begin Write(''> ''); ReadLn(X); repeat Y:=Z(X); WriteLn(Format(''%d is %d.'' , [X,Y])); X:=Y; until X=4; WriteLn(''4 is magic.''); end.

Probablemente espacio para un poco más de apretar ... :-P


J, 107 112 caracteres

''4 is magic.'',~}:(''.'',~":@{.,'' is '',":@{:)"1]2&{./. (]{&(#.100 4$,#:3 u:ucp''䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺''))^:a:

(Nueva línea para legibilidad solamente)

Uso y salida:

''4 is magic.'',~}:(''.'',~":@{.,'' is '',":@{:)"1]2&{./.(]{&(#.100 4$,#:3 u:ucp''䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺''))^:a:12 12 is 6. 6 is 3. 3 is 5. 5 is 4. 4 is magic.


Java (con plantilla), 308 290 286 282 280 caracteres

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

Estoy seguro de que Groovy se desharía de gran parte de eso.

Explicación y formato (todos los comentarios, líneas nuevas y espacios en blanco iniciales / finales eliminados en el recuento):

Razonablemente sencillo, pero

//boilerplate class A{ public static void main(String[]a){ //i is current/left number, j right/next number. i=4 signals to start //by reading input int i=4,j=0; for(;;) //print in the form "<left> is <right>." System.out.printf( "%d is %s.%n", i=i==4? //<left>: if i is 4 <left> will be a new starting number new java.util.Scanner(System.in).nextInt(): //otherwise it''s the next val j, i!=4? //use string to map number to its length (:;< come after 9 in ASCII) //48 is value of ''0''. store in j for next iteration j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48: //i==4 is special case for right; print "magic" "magic"); } }

Editar: ya no use hexadecimal, esto es menos pulsaciones de teclas


JavaScript 1.8 (SpiderMonkey) - 153 caracteres

l=''4335443554366887798866555766''.split('''') for(b=readline();(a=+b)-4;print(a,''is ''+b+''.''))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10]) print(''4 is magic.'')

Uso: echo 42 | js golf.js echo 42 | js golf.js

Salida:

42 is 8. 8 is 5. 5 is 4. 4 is magic.

Con bonus - 364 caracteres

l=''zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety''.split('' '') z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?'' ''+l[a%10]:'''') for(b=+readline();(a=b)-4;print(z(a),''is ''+z(b)+''.''))b=z(a).replace('' '','''').length print(''four is magic.'')

Salida:

ninety nine is ten. ten is three. three is five. five is four. four is magic.


Lua, 176 Personajes

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

o

o={[0]=4,3,3,5,4,4 ,3,5,5,4,3,6,6,8,8 ,7,7,9,8,8}t={3,6, 6,5,5,5,7,6,6}n= 0+io.read()while n ~= 4 do a= o[n ]or o[n%10]+t[(n -n%10)/10]print( n.." is "..a.."." )n=a end print"4 is magic."


Perl, alrededor de 147 caracteres

Basada libremente en la solución Platinum Azure:

chop ($_.= <>);@ u="433 5443554 366 887 798 866 555 766 "=~ //d /gx ;#4 sub r{4 -$_ ?$_ <20 ?$u [$_ ]:( $''? $u[ $''] :0) +$u[18+$&]:magic}print" $_ is ",$_=r(),''.''while //d /x; 444


Perl: 148 caracteres

(Perl: 233 181 212 206 200 199 198 185 179 149 148 caracteres)

  • Se movió el hash de excepciones al conjunto de unidades. Esto resultó en que pude cortar muchos personajes :-)
  • mobrule señaló un error desagradable. La solución rápida agrega 31 caracteres, ¡ay!
  • Refactorizado para cero caso especial, golf suave también.
  • ¿Acceso directo a la lista para un solo uso en lugar de almacenar en una matriz? ¡Oh sí!
  • TANTO REFACTANTE por solo UN personaje sangriento. Esto, verdaderamente, es la vida de un golfista. :-(
  • Vaya, fácil corrección de espacio en blanco. 198 ahora.
  • Refactorado algún código redundante.
  • La última palabra clave devuelta en r es innecesaria, se afeitó un poco más.
  • Refactorización masiva por comentarios; lamentablemente solo pude obtenerlo hasta 149 porque tuve que corregir un error que estaba presente tanto en mi código anterior como en las versiones de los comentaristas.
  • Intentando la palabra mágica "magia".

Hagamos rodar esta bola con un modesto intento en Perl.

@u=split'''',''4335443554366887798866555766'';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).". "while$_

Trucos:

¡Demasiados!


Python 2.x, 144 150 154 166 caracteres

Esto separa el número en decenas y unidades y las resume. La propiedad indeseable del operador pseudo ternario a and b or c que devuelve c si b es 0 se está abusando aquí.

n=input() x=0x4d2d0f47815890bd2 while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p print"4 is magic."

La versión anterior ingenua (150 caracteres). Solo codifica todas las longitudes como un entero.

n=input() while n-4:p=3+int(''1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29'',36)/10**n%10;print n,"is %d."%p;n=p print"4 is magic."


Python, 129 133 137 148 caracteres

Como precalentamiento, esta es mi primera versión (mejora un par de caracteres con respecto al mejor Python anterior).

PD. Después de algunas redacciones ahora es de unos veinte carbonos más cortos:

n=input() while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,''is %d.''%p;n=p print''4 is magic.''


Versión C ++ Stdio, minificado: 196 caracteres

#include <cstdio> #define P;printf( char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d./n%d",p,p);}P" is magic./n");}

Versión de C ++ Iostreams, minificado: 195 caracteres

#include <iostream> #define O;std::cout<< char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<"./n"<<p;}O" is magic./n";}

Original, sin minificar: 344 caracteres

#include <cstdio> int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 }; int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 }; int n(int n) { return n<20 ? ones[n] : tens[n/10] + ones[n%10]; } int main(int p) { scanf("%d", &p); while(p!=4) { int q = n(p); printf("%i is %i/n", p, q); p = q; } printf("%i is magic/n", p); }


PhP Code

function get_num_name($num){ switch($num){ case 1:return ''one''; case 2:return ''two''; case 3:return ''three''; case 4:return ''four''; case 5:return ''five''; case 6:return ''six''; case 7:return ''seven''; case 8:return ''eight''; case 9:return ''nine''; } } function num_to_words($number, $real_name, $decimal_digit, $decimal_name){ $res = ''''; $real = 0; $decimal = 0; if($number == 0) return ''Zero''.(($real_name == '''')?'''':'' ''.$real_name); if($number >= 0){ $real = floor($number); $decimal = number_format($number - $real, $decimal_digit, ''.'', '',''); }else{ $real = ceil($number) * (-1); $number = abs($number); $decimal = number_format($number - $real, $decimal_digit, ''.'', '',''); } $decimal = substr($decimal, strpos($decimal, ''.'') +1); $unit_name[1] = ''thousand''; $unit_name[2] = ''million''; $unit_name[3] = ''billion''; $unit_name[4] = ''trillion''; $packet = array(); $number = strrev($real); $packet = str_split($number,3); for($i=0;$i<count($packet);$i++){ $tmp = strrev($packet[$i]); $unit = $unit_name[$i]; if((int)$tmp == 0) continue; $tmp_res = ''''; if(strlen($tmp) >= 2){ $tmp_proc = substr($tmp,-2); switch($tmp_proc){ case ''10'': $tmp_res = ''ten''; break; case ''11'': $tmp_res = ''eleven''; break; case ''12'': $tmp_res = ''twelve''; break; case ''13'': $tmp_res = ''thirteen''; break; case ''15'': $tmp_res = ''fifteen''; break; case ''20'': $tmp_res = ''twenty''; break; case ''30'': $tmp_res = ''thirty''; break; case ''40'': $tmp_res = ''forty''; break; case ''50'': $tmp_res = ''fifty''; break; case ''70'': $tmp_res = ''seventy''; break; case ''80'': $tmp_res = ''eighty''; break; default: $tmp_begin = substr($tmp_proc,0,1); $tmp_end = substr($tmp_proc,1,1); if($tmp_begin == ''1'') $tmp_res = get_num_name($tmp_end).''teen''; elseif($tmp_begin == ''0'') $tmp_res = get_num_name($tmp_end); elseif($tmp_end == ''0'') $tmp_res = get_num_name($tmp_begin).''ty''; else{ if($tmp_begin == ''2'') $tmp_res = ''twenty''; elseif($tmp_begin == ''3'') $tmp_res = ''thirty''; elseif($tmp_begin == ''4'') $tmp_res = ''forty''; elseif($tmp_begin == ''5'') $tmp_res = ''fifty''; elseif($tmp_begin == ''6'') $tmp_res = ''sixty''; elseif($tmp_begin == ''7'') $tmp_res = ''seventy''; elseif($tmp_begin == ''8'') $tmp_res = ''eighty''; elseif($tmp_begin == ''9'') $tmp_res = ''ninety''; $tmp_res = $tmp_res.'' ''.get_num_name($tmp_end); } break; } if(strlen($tmp) == 3){ $tmp_begin = substr($tmp,0,1); $space = ''''; if(substr($tmp_res,0,1) != '' '' && $tmp_res != '''') $space = '' ''; if($tmp_begin != 0){ if($tmp_begin != ''0''){ if($tmp_res != '''') $tmp_res = ''and''.$space.$tmp_res; } $tmp_res = get_num_name($tmp_begin).'' hundred''.$space.$tmp_res; } } }else $tmp_res = get_num_name($tmp); $space = ''''; if(substr($res,0,1) != '' '' && $res != '''') $space = '' ''; $res = $tmp_res.'' ''.$unit.$space.$res; } $space = ''''; if(substr($res,-1) != '' '' && $res != '''') $space = '' ''; if($res) $res .= $space.$real_name.(($real > 1 && $real_name != '''')?''s'':''''); if($decimal > 0) $res .= '' ''.num_to_words($decimal, '''', 0, '''').'' ''.$decimal_name.(($decimal > 1 && $decimal_name != '''')?''s'':''''); return ucfirst($res); }

//////////// testing ////////////////

$str2num = 12; while($str2num!=4){ $str = num_to_words($str2num, '''', 0, ''''); $str2num = strlen($str)-1; echo $str . ''='' . $str2num .''<br/>''; if ($str2num == 4) echo ''four is magic''; }

////// Results /////////

Twelve =6 Six =3 Three =5 Five =4 four is magic


Ruby, 164 characters

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

decoded:

n = gets.to_i s = "03354435543668877987" if n == 0 puts "0 is 4." else puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4 end puts "4 is magic."


Shameless Perl with Number Words (329 characters)

Adapted fairly directly from P Daddy''s C code, with some tweaks to p() to make it do the same thing using Perl primitives instead of C ones, and a mostly-rewritten mainloop. See his for an explanation. Newlines are all optional.

@t=(qw(zero one two three four five six sM eight nine tL elM twelve NP 4P fifP 6P 7P 8O 9P twLQ NQ forQ fifQ 6Q 7Q 8y 9Q en evL thir eL tO ty 4SmagicT)," is ","./n"); sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e; print;length}$_=<>;chop;while($_-4){ $_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_; p 35;p$_;p 36}p 34

Side note: it''s too bad that perl print just returns true/false; if it returned a count it would save me 7 strokes.


Pitón:

#!/usr/bin/env python # Number of letters in each part, we don''t count spaces Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 ) Smalls = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 ) Teens = ( 6, 6, 8, 8, 7, 7, 9, 8, 8 ) def Count(n): if n > 10 and n < 20: return Teens[n-11] return Smalls[n % 10 ] + Decades [ n / 10 ] N = input() while N-4: Cnt = Count(N) print "%d is %d" % ( N, Cnt) N = Cnt print "4 is magic"


C # 314 286 283 274 289 273 252 caracteres.

Squished:

252

Normal:

using C = System.Console; class P { static void Main() { var x = "4335443554366877798866555766"; int m, o, v = int.Parse(C.ReadLine()); do { C.Write("{0} is {1}./n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48)); } while (o != 4); C.ReadLine(); } }

Editar Dykam: Hizo algunas inserciones y cambios cuidadosos:

  • Cambió el l.ToString () en un molde al object de la string "magic" .
  • Creé una variable temporal o , para poder mover la break fuera del ciclo for , es decir, dar como resultado un do-while .
  • Inline the o assignment, así como la asignación v , continuando al insertar el cálculo de l en los argumentos de la función por completo, eliminando la necesidad de l . También se incluye la asignación de m .
  • Se eliminó un espacio en int[] x , int[]x es legítimo también.
  • Intenté transformar la matriz en una transformación de cadena, pero using System.Linq fue demasiado para hacer de esto una mejora.

Editar 2 Dykam Cambió la matriz int a una matriz de caracteres / cadena, agregó los aritméticos adecuados para corregir esto.


Common Lisp 157 Chars

Nueva versión más conforme, ahora leyendo entrada estándar e ignorando espacios y guiones:

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

En forma legible para los humanos:

(labels ((g (x) (if (= x 4) (princ "4 is magic.") (let ((n (length (remove-if (lambda(x) (find x " -")) (format nil "~r" x))))) (format t"~a is ~a.~%" x n) (g n))))) (g (read)))

Y algunas ejecuciones de prueba:

>24 24 is 10. 10 is 3. 3 is 5. 5 is 4. 4 is magic. >23152436 23152436 is 64. 64 is 9. 9 is 4. 4 is magic.

Y la versión de bonificación, a 165 caracteres:

(labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

Dar

>24 twenty-four is ten. ten is three. three is five. five is four. four is magic. >234235 two hundred thirty-four thousand two hundred thirty-five is forty-eight. forty-eight is ten. ten is three. three is five. five is four. four is magic.


Lua 185 190 199

added periods, added io.read, removed ()''s on last print

n=io.read();while(n~=4)do m=(''43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:''):sub(n+1):byte()-48;print(n,'' is '',m,''.'')n=m;end print''4 is magic.''

with line breaks

n=io.read() while (n~=4) do m=(''43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:''):sub(n+1):byte()-48; print(n,'' is '',m,''.'') n=m; end print''4 is magic.''


C++, 171 characters (#include omitted)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d./n",x,y);puts("4 is magic.");}


Ruby, 141 caracteres:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? ''magic'': n}.";n==s &&break}


while(true) { string a; ReadLine(a) WriteLine(4); }