Convertir enteros a palabras inglesas

21

El objetivo de este código de golf es convertir enteros a palabras en inglés.

El programa solicita entradas. Si esta entrada no es un entero, imprime NaN. Si es un número entero, conviértalo a palabras en inglés e imprima estas palabras. Entrada mínima: 0 (cero). Entrada máxima: 9000 (nueve mil).
Entonces, 5devuelve five(el caso no importa) y 500devuelve five hundredo five-hundred(los guiones no importan).

Algunas otras reglas:

A oneantes hundredo thousandes opcional: one hundredes correcto, pero hundredtambién (si la entrada es, 100por supuesto).

La palabra anden, por ejemplo, también one hundred and forty fivees opcional.

El espacio en blanco es importante. Entonces, para 500, five-hundredo five hundredes correcto, pero fivehundredno lo es.

¡Buena suerte!

ProgramFOX
fuente
Hay una respuesta no escrita aquí rgagnon.com/javadetails/java-0426.html .
Esta respuesta en SO hace cosas similares pero no es code-golf.
ST3

Respuestas:

7

Perl 281 bytes

print+0eq($_=<>)?Zero:"@{[((@0=($z,One,Two,Three,Four,Five,@2=(Six,Seven),
Eight,Nine,Ten,Eleven,Twelve,map$_.teen,Thir,Four,@1=(Fif,@2,Eigh,Nine)))
[$_/1e3],Thousand)x($_>999),($0[($_%=1e3)/100],Hundred)x($_>99),
($_%=100)>19?((Twen,Thir,For,@1)[$_/10-2].ty,$0[$_%10]):$0[$_]]}"||NaN

Se agregaron nuevas líneas para la cordura horizontal. Lo anterior se puede usar de forma interactiva o canalizando un valor a través de stdin.

Funciona correctamente para todos los valores enteros en el rango [0, 19999] , los valores fuera de este rango exhiben un comportamiento indefinido. Los valores no enteros se truncarán hacia cero y, como tal, solo se informarán los valores que realmente no sean numéricos NaN.

Uso de la muestra:

for $n (14, 42, 762, 2000, 6012, 19791, 1e9, foobar, 17.2, -3) {
  print "$n: ", `echo $n | perl spoken-numbers.pl`, $/;
}

Salida de muestra:

14: Fourteen
42: Forty Two
762: Seven Hundred Sixty Two
2000: Two Thousand 
6012: Six Thousand Twelve
19791: Nineteen Thousand Seven Hundred Ninety One
1000000000: Thousand 
foobar: NaN
17.2: Seventeen
-3: Nine Hundred Ninety Seven
primo
fuente
"1000000000: Mil"? ¿Y no debería 17.2 imprimir "NaN"?
DavidC
55
@DavidCarraher "... los valores fuera de este rango exhiben un comportamiento indefinido . Los valores no enteros se truncarán hacia cero y, como tal, solo los valores que realmente no sean numéricos informarán NaN".
primo
No soy un experto en Perl, así que hago esta pregunta: ¿este programa solicita información?
ProgramFOX
@ProgramFOX Lo actualicé para leer un valor de stdin (si se ejecuta de forma interactiva, solicitará al usuario un valor), en lugar de como una función.
primo
13

JavaScript (375)

Probablemente un intento terrible, pero de todos modos, aquí va ...

alert(function N(s,z){return O="zero,one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,,fif,,,eigh,,,,twen,,for".split(","),(z?O[s]||O[s-10]||O[s-20]:s<13?N(s,1):s<20?N(s,1)+"teen":s<100?N(a=20+(s/10|0),1)+"ty"+(s%10?" "+N(s%10):""):s<1e3?N(s/100|0)+" hundred"+(s%100?" "+N(s%100):""):s<1e5?N(s/1e3|0)+" thousand"+(s%1e3?" "+N(s%1e3):""):0)||NaN}(prompt()))

Bonito impreso (como una función):

function N(s,z) {
  return O = "zero,one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,,fif,,,eigh,,,,twen,,for".split(","),
      (z? O[s] || O[s-10] || O[s-20]
       : s < 13?  N(s,1)
       : s < 20?  N(s,1) + "teen"
       : s < 100? N(a=20+(s/10|0),1) + "ty" + (s%10?" "+N(s%10):"")
       : s < 1e3?  N(s/100|0) +  " hundred" + (s%100?" "+N(s%100):"")
       : s < 1e5?  N(s/1e3|0) + " thousand" + (s%1e3?" "+N(s%1e3):"") : 0) || NaN
}

Conversión de muestra (tenga en cuenta que incluso NaNsale cuando está fuera de límites, es decir, entrada no válida):

540: five hundred forty
4711: four thousand seven hundred eleven
7382: seven thousand three hundred eighty two
1992: one thousand nine hundred ninety two
hutenosa: NaN
1000000000: NaN
-3: NaN
Luciérnaga
fuente
+1es bastante difícil hacerlo mejor en un lenguaje como javascript. (puedes quitar el espacio N(s,z) {returnpara ahorrar 1 personaje)
Math chiller
Oh, jaja, debe haber perdido ese. También parece que me he perdido un montón de caracteres en la Ocadena. Lo arreglaré ..
FireFly
11

Mathematica 60 57

f = ToString@#~WolframAlpha~{{"NumberName", 1}, "Plaintext"} &

Uso:

f[500]

quinientos

Editar:

InputString[]~WolframAlpha~{{"NumberName", 1}, "Plaintext"}
alephalpha
fuente
3
Esto realmente no responde la pregunta. Dije que el usuario tiene que ingresar un número (usando la línea de comando, o un cuadro de aviso, por ejemplo), y luego su programa debería mostrar las palabras (en la línea de comando, o en un cuadro de mensaje, por ejemplo). Su código es solo una función para convertirlo, y su programa no solicita información.
ProgramFOX
@ProgramFOX dice 'El usuario ingresa algo'. Eso no significa "El programa solicita información".
MrZander
@MrZander: Bueno, 'El programa solicita información' fue en realidad lo que quise decir. Actualizo mi pregunta, pero por supuesto, sería injusto si no votara la respuesta de alephalpha, por lo que obtuvo mi +1
ProgramFOX el
8

Ceceo, 72 56 caracteres

Me doy cuenta de 1) que esto es viejo, y 2) que depende completamente de la biblioteca estándar para funcionar, pero el hecho de que pueda hacer que el sistema de impresión c-lisp haga este tipo de cosas siempre me ha impresionado. Además, esto de hecho toma la entrada de un usuario, la convierte e imprime.

(format t "~:[NaN~;~:*~r~]" (parse-integer (read-line) :junk-allowed t))

Tiene un total de 72 caracteres.

  • :junk-allowed hace que parse-integer devuelva nil en caso de error en lugar de generar un error.
  • ~:[if-nil~;if-non-nill] condicional predicado en nil, maneja NaN donde sea necesario
  • ~:* realiza una copia de seguridad de la interpretación del argumento para volver a consumir la entrada
  • ~r imprime el número como una cadena de palabras en inglés, según lo solicitado, excepto con la puntuación corregida completa

Muestra:

17823658
seventeen million, eight hundred and twenty-three thousand, six hundred and fifty-eight

192hqfwoelkqhwef9812ho1289hg18hoif3h1o98g3hgq
NaN

Información de Lisp principalmente de Practical Common Lisp .

Edición, golf correctamente hasta 56 caracteres

(format t "~:[NaN~;~:*~r~]"(ignore-errors(floor(read))))

Esta versión funciona de manera bastante diferente. En lugar de leer una línea y convertirla, invoca al lector de lisp para interpretar la entrada como una expresión s de lisp, intenta usarla como un número y, si se producen errores, los ignora y producen nil para alimentar la cadena de formato condicional. Esta puede ser la primera vez que veo que lisp produce un programa realmente conciso ... ¡Diversión!

  • (read) Invoca al lector / analizador de lisp para leer una expresión de la entrada estándar y convertirla en un objeto apropiado
  • (floor) intenta convertir cualquier tipo numérico en el entero inferior más cercano, los tipos no numéricos provocan un error
  • (ignore-errors ...) hace lo que dice en la lata, atrapa e ignora cualquier error en la expresión encerrada, regresando nil para alimentar la rama NaN de la cadena de formato
Tom Scogland
fuente
Ciertamente no hay problema en que la pregunta anterior :) Edité su respuesta para incluir el nombre del idioma y el recuento de caracteres en un encabezado.
ProgramFOX
Gracias por las ediciones, todavía no tengo la sintaxis de Stack * para estas cosas. Regresé y solucioné un error que cometí en la descripción del condicional en la cadena de formato también.
Tom Scogland
3

PHP, 327 310 308 bytes

<?$a=['',one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,0,fif,0,0,eigh];echo($n=$argv[1])>999?$a[$n/1000].' thousand ':'',$n%1000>99?$a[$n/100%10].' hundred ':'',$n?($k=$n%100)<20?($a[$k]?:$a[$k%10]).[teen][$k<13]:[2=>twen,thir,'for',fif,six,seven,eigh,nine][$k/10].'ty '.$a[$k%10]:zero;

toma el número como parámetro, funciona para 0 <= n <= 12999

Descompostura

// define names
$a=['',one,two,three,four,five,six,seven,eight,nine,
    ten,eleven,twelve,thir,0,fif,0,0,eigh];
// print ...
echo
    ($n=$argv[1])>999?$a[$n/1000].' thousand ':'',                  // thousands
    $n%1000>99?$a[$n/100%10].' hundred ':'',                        // hundreds
    $n?
        // if remains <20:
        ($k=$n%100)<20?
            ($a[$k]?:$a[$k%10]) // no value at index (0,14,16,17,19)? value from index%10
            .[teen][$k<13]      // append "teen" for $k>12
        // else:
        :[2=>twen,thir,'for',fif,six,seven,eigh,nine][$k/10].'ty '  // tens
        .$a[$k%10]                                                  // ones
    // "zero" for $n==0
    :zero
;
Titus
fuente
2

SAS, 70 caracteres

data;window w n;display w;if n=. then put 'NaN';else put n words.;run;

Las declaraciones windowy displayabren el símbolo del sistema SAS. La entrada para nva en la línea 1. Esto aprovecha el formato SAS words.que imprimirá el número como una palabra o serie de palabras con "y", "" y "-" según corresponda.

Alex A.
fuente
2

PHP

777 caracteres

Este es definitivamente un intento terrible, pero no puedes acusarme de aprovechar las lagunas, además es un número muy afortunado. Gracias a ProgramFOX por el consejo.

<?php $i=9212;$b = array('zero','one','two','three','four','five','six','seven','eight','nine');$t='teen';$c = array('ten','eleven','tweleve','thir'.$t,$b[4].$t,'fif'.$t,$b[6].$t,$b[7].$t,$b[8].$t,$b[9].$t);$d = array('','','twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety');$e='hundred';$f='thousand';$j=str_split($i);if (strlen($i)===1){$a=$b[$i];}elseif (strlen($i)===3){$k=1;$a=$b[$j[0]].' '.$e.' '.x($j,$k);}elseif (strlen($i)===4){$k=2;$a=$b[$j[0]].' '.$f.' '.$b[$j[1]].' '.$e.' '.x($j,$k);}elseif (substr($i, -2, 1)==='1'){$a=$c[$j[1]];}else{$a=$d[$j[0]].' '.$b[$j[1]];}$a = str_replace('zero hundred','',$a);echo $a;function x($j,$k){global $i, $b, $c, $d;if (substr($i, -2, 1)==='1'){return $c[$j[$k+1]];}else{return $d[$j[$k]].' '.$b[$j[$k+1]];}}

Mano larga

<?php
// Input
$i=9212;
// 0-9
$b = array('zero','one','two','three','four','five','six','seven','eight','nine');
// 10-19 (Very tricky)
$t='teen';
$c = array('ten','eleven','tweleve','thir'.$t,$b[4].$t,'fif'.$t,$b[6].$t,$b[7].$t,$b[8].$t,$b[9].$t); 
// Left digit of 20-99
$d = array('','','twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety');
// Hundreds
$e='hundred';
// Thousands
$f='thousand';
// Split input
$j=str_split($i);
// 1 digit inputs
if (strlen($i)===1){$a=$b[$i];}
// 3 digit input
elseif (strlen($i)===3){$k=1;$a=$b[$j[0]].' '.$e.' '.x($j,$k);}
// 4 digit input
elseif (strlen($i)===4){$k=2;$a=$b[$j[0]].' '.$f.' '.$b[$j[1]].' '.$e.' '.x($j,$k);}
// 10-19
elseif (substr($i, -2, 1)==='1'){$a=$c[$j[1]];}
// 20-99
else{$a=$d[$j[0]].' '.$b[$j[1]];}
// Fix for thousand numbers
$a = str_replace('zero hundred','',$a);
// Result
echo $a;
// Abstracted function last 2 digits for 3 and 4 digit numbers
function x($j,$k){
    global $i, $b, $c, $d;
    // 10-19
    if (substr($i, -2, 1)==='1'){return $c[$j[$k+1]];}
    // 20-99
    else{return $d[$j[$k]].' '.$b[$j[$k+1]];}
}
ganso
fuente
1
Creo que se puede acortar su código mediante la creación de arreglos como: array('zero','one','two').
ProgramFOX
@ProgramFOX o incluso ['zero','one','two'](php 5.4+). Y si no te importa E_NOTICE, [zero,one,two]también funcionaría.
primo
Debería actualizarlo, pero 777 es un número tan afortunado.
Goose
+1 por tus esfuerzos. PHP está trágicamente subrepresentado en el código de golf.
primo
1

Python 2.x - 378

Derivada de la respuesta de Fireflys, aunque cambiando Ppara incluir millones o trillones, etc., podría usarse recursivamente para cualquier rango de números positivos. Esto también admite valores de hasta 999,999

O=",one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,,fif,,,eigh,,,,twen,thir,for,fif,,,eigh,".split(",")
P=",thousand".split(',')
def N(s,p=0):
 h,s=divmod(s,1000);x=N(h,p+1)if h>0 else" "
 if s<20:x+=O[s]or O[s-10]+["","teen"][s>12]
 elif s<100:x+=(O[s/10+20]or O[s/10])+"ty"+N(s%10)
 else:x+=N(s/100)+"hundred"+N(s%100)
 return x+" "+P[p]
print N(input())

Prueba de muestra (la entrada es <<<, la salida es >>>):

<<< 1234
>>> one thousand two hundred thirty four

<<< 999999
>>>  nine hundred ninety nine   thousand nine hundred ninety nine

Aunque, si alguien puede explicar este extraño problema de "desbordamiento del búfer" que tengo, eso sería genial ...

<<< -1
>>>  nine hundred ninety nine

<<< -2
>>>  nine hundred ninety eight

fuente
print divmod(-2,1000) #-> (-1, 998)
primo
Oh por supuesto. Estaba pensando que podría tomar un valor absoluto o algo así. Pero hay -1*1000y un "resto" de 998.
1

SmileBASIC, 365 Trescientos cuarenta y siete bytes

DIM N$[22]D$="OneTwoThreeFourFiveSixSevenEightNineTenElevenTwelveThirFourFifSixSevenEighNineTwenFor
WHILE LEN(D$)INC I,D$[0]<"_
INC N$[I],SHIFT(D$)WEND
INPUT N
W=N MOD 100C%=N/100MOD 10M%=N/1E3T=W<20X=W/10>>0?(N$[M%]+" Thousand ")*!!M%+(N$[C%]+" Hundred ")*!!C%+(N$[X+10+(X==2)*8+(X==4)*7]+"ty "+N$[N MOD 10])*!T+N$[W*T]+"teen"*(T&&W>12)+"Zero"*!N

Hay un espacio final si los últimos uno o dos dígitos son 0.

12Me21
fuente
0

MOO - 55 caracteres

player:tell($string_utils:english_number(read(player)))

O, si no necesito imprimir en "stdout" - 42 caracteres: $string_utils:english_number(read(player))

Nota: este código no imprime ningún aviso en la salida estándar e imprime en zerolugar de NaNcuando la entrada no es un número.

Como beneficio adicional, este código puede manejar cualquier número dentro de los límites del lenguaje mu ( 2147483647- -2147483648).

pppery
fuente
0

Wolfram Language 27 40 bytes

Haciendo uso de la función nativa IntegerName,

 Check[Input[]~IntegerName~"Words","NaN"]

Lo anterior solicita la entrada del usuario. La implementación actual devuelve "NaN" si el usuario ingresa algo que no sea un entero.


Algunos ejemplos (con entradas preestablecidas) :

 Check[243~IntegerName~"Words","NaN"]

doscientos cuarenta y tres


 Check[1234567890~IntegerName~"Words","NaN"]   

mil doscientos treinta y cuatro millones quinientos sesenta y siete mil ochocientos noventa


 Check["abc"~IntegerName~"Words","NaN"]  

Yaya

DavidC
fuente
0

Python 2 , 333 bytes

def f(n):S=str.split;D=S('z one two three four five six seven eight nine');K=' fif six seven eigh nine';k=n/1000;n,m=n/100%10,n%100;e,d=m/10,m%10;return' '.join([k and f(k),'thousand']*(k>0)+[D[n],'hundred']*(n>0)+([S('ten eleven twelve thir four'+K)[d]+'teen'*(d>2)]if 9<m<20else[S('twen thir for'+K)[e-2]+'ty']*(e>0)+[D[d]]*(d>0)))

Pruébalo en línea!

Esto es bueno para 1 a 999,999, inclusive.

Chas Brown
fuente
0

Pyth, 239 242 bytes

L:rjdb6"  +"dAm+cd;"nine"," one two three four five six seven eight""  twen thir for fif six seven eigh"|y_.ey+Wk.e?Y?thZjd,?hZ+@HhZ"ty"""@GeZ@+c"ten eleven twelve"d+R"teen"+c"thir four"d>H5eZ?hZ+@GhZ" hundred"""c.[03_b]1"thousand"c_jQT3"zero

La entrada es un entero en el rango [0-999,999]. Pruébelo en línea aquí . Explicación pendiente.

Versión anterior, operación muy similar, pero no admite 0:

L:rjdb6"  +"dJc" one two three four five six seven eight nine"dKc"  twen thir for fif six seven eigh nine"dy_.ey+Wk.e?Y?thZjd,?hZ+@KhZ"ty"""@JeZ@+c"ten eleven twelve"d+R"teen"+c"thir four"d>K5eZ?hZ+@JhZ" hundred"""c.[03_b]1"thousand"c_jQT3

Explicación de la versión anterior:

Implicit: Q=eval(input()), d=" "

Step 1: output formatting helper function
L:rjdb6"  +"d   
L               Define a function, y(b):
   jdb          Join b on spaces
  r   6         Strip whitespace from beginning and end
 :              In the above, replace...
       "  +"    ... strings of more than one space...
            d   ... with a single space

Step 2: Define number lookup lists
Jc"..."dKc"..."d   
  "..."            Lookup string
 c     d           Split the above on spaces
J                  Store in J - this is list of unit names
        Kc"..."d   As above, but storing in K - this is list of tens names, without "ty"

Step 3: Bringing it all together
y_.ey+Wk.e?Y?thZjd,?hZ+@KhZ"ty"""@JeZ@+c"ten eleven twelve"d+R"teen"+c"thir four"d>K5eZ?hZ+@JhZ" hundred"""c.[03_b]1"thousand"c_jQT3   
                                                                                                                                jQT    Get digits of Q
                                                                                                                               _       Reverse
                                                                                                                              c    3   Split into groups of 3
  .e                                                                                                                                   Map the above, element as b, index as k, using:
                                                                                                                _b                       Reverse the digits in the group
                                                                                                            .[03                         Pad the above on the left with 0 to length 3
                                                                                                           c      ]1                     Chop at index 1 - [1,2,3] => [[1],[2,3]]
        .e                                                                                                                               Map the above, element as Z, index as Y, using:
          ?Y                                                                                                                               If second element in the group (i.e. tens and units):
            ?thZ                                                                                                                             If (tens - 1) is non-zero (i.e. 0 or >=2):
                   ?hZ                                                                                                                         If tens is non-zero:
                       @KhZ                                                                                                                      Lookup in tens names
                      +    "ty"                                                                                                                  Append "ty"
                                                                                                                                               Else:
                               ""                                                                                                                Empty string
                  ,                                                                                                                            Create two-element list of the above with...
                                 @JeZ                                                                                                          ... lookup units name
                jd                                                                                                                             Join the above on a space - this covers [0-9] and [20-99]
                                                                                                                                             Else:
                                                                     c"thir four"d                                                             ["thir", "four"]
                                                                    +             >K5                                                          Append last 5 element of tens names ("fif" onwards)
                                                            +R"teen"                                                                           Append "teen" to each string in the above
                                      +c"ten eleven twelve"d                                                                                   Prepend ["ten", "eleven", "twelve"]
                                     @                                               eZ                                                        Take string at index of units column - this covers [10-19]
                                                                                                                                           Else: (i.e. hundreds column)
                                                                                       ?hZ                                                   If hundreds column is non-zero:
                                                                                           @JhZ                                                Lookup units name
                                                                                          +    " hundred"                                      Append " hundred"
                                                                                                         ""                                  Else: empty string
                                                                                                                                         Result of map is two element list of [hundreds name, tens and units name]
      Wk                                                                                                                                 If k is nonzero (i.e. dealing with thousands group)...
     +                                                                                                              "thousand"           ... Append "thousand"
    y                                                                                                                                    Apply output formatting (join on spaces, strip, deduplicate spaces)
                                                                                                                                       Result of map is [units group string, thousands group string]
 _                                                                                                                                     Reverse group ordering to put thousands back in front
y                                                                                                                                      Apply output formatting again, implicit print
Sok
fuente