Conversione di numeri interi in parole inglesi


21

L'obiettivo di questo codice golf è convertire numeri interi in parole inglesi.

Il programma richiede l'immissione. Se questo input non è un numero intero, stampa NaN. Se è un numero intero, convertilo in parole inglesi e stampa queste parole. Ingresso minimo: 0 (zero). Input massimo: 9000 (nove mila).
Quindi, 5restituisce five(il caso non ha importanza) e 500restituisce five hundredo five-hundred(i trattini non contano).

Alcune altre regole:

Un oneprima hundredo thousandè facoltativo: one hundredè corretto, ma hundredanche (se l'ingresso è 100ovviamente).

Anche la parola andin per esempio one hundred and forty fiveè facoltativa.

Lo spazio bianco conta. Quindi, per 500, five-hundredo five hundredè corretto, ma fivehundrednon lo è.

In bocca al lupo!



Questa risposta in SO fa cose simili ma non è code-golf.
ST3,

Risposte:


7

Perl 281 byte

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

Newlines aggiunti per sanità mentale orizzontale. Quanto sopra può essere utilizzato in modo interattivo o eseguendo il piping di un valore tramite stdin.

Funziona correttamente per tutti i valori interi nell'intervallo [0, 19999] , i valori al di fuori di questo intervallo mostrano un comportamento indefinito. I valori non interi verranno troncati verso zero e, come tali, verranno riportati solo i valori che sono veramente non numerici NaN.

Esempio di utilizzo:

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

Uscita campione:

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

"1000000000: mille"? E non dovrebbe 17.2 stampare "NaN"?
DavidC,

5
@DavidCarraher "... i valori al di fuori di questo intervallo mostrano un comportamento indefinito . I valori non interi verranno troncati verso zero e, come tali, verranno riportati solo i valori che sono veramente non numerici NaN."
primo

Non sono un esperto del Perl, quindi faccio questa domanda: questo programma richiede input?
Programma FOX

@ProgramFOX L'ho aggiornato per leggere un valore da stdin (se eseguito in modo interattivo, richiederà all'utente un valore), anziché come una funzione.
primo

13

JavaScript (375)

Probabilmente un terribile tentativo, ma comunque qui 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()))

Abbastanza stampato (come funzione):

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
}

Conversione del campione (si noti che emette anche NaNquando è fuori dai limiti, ovvero input non valido):

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

+1è abbastanza difficile fare meglio in una lingua come javascript. (puoi rimuovere lo spazio N(s,z) {returnper salvare 1 carattere)
Chiller matematico

Oh, ahah, deve aver perso quello. Mi sembra anche di aver perso un sacco di caratteri nella Ostringa. Lo aggiusterò ..
FireFly,

11

Mathematica 60 57

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

Uso:

f[500]

cinquecento

Modificare:

InputString[]~WolframAlpha~{{"NumberName", 1}, "Plaintext"}

3
Questo non risponde davvero alla domanda. Ho detto che l'utente deve inserire un numero (usando la riga di comando, o una finestra di prompt per esempio), e quindi il tuo programma dovrebbe generare le parole (sulla riga di comando, o in una finestra di messaggio per esempio). Il tuo codice è solo una funzione per convertirlo e il tuo programma non richiede input.
Programma FOX

@ProgramFOX dice "L'utente inserisce qualcosa". Ciò non significa "Il programma richiede l'immissione".
MrZander,

@MrZander: Beh, "Il programma richiede input" era in realtà ciò che intendevo. Aggiornamento la mia domanda, ma ovviamente sarebbe ingiusto se non votassi la risposta di alephalpha, quindi ha ottenuto il mio +1
ProgramFOX

8

Lisp, 72 56 caratteri

Mi rendo conto 1) che questo è vecchio e 2) che si basa interamente sulla libreria standard per funzionare, ma il fatto che sia possibile ottenere il sistema di stampa c-lisp per fare questo tipo di cose mi ha sempre colpito. Inoltre, questo in effetti prende l'input da un utente, lo converte e lo stampa.

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

È composto da 72 caratteri.

  • :junk-allowed fa sì che parse-integer restituisca zero in caso di errore anziché generare un errore.
  • ~:[if-nil~;if-non-nill] condizionato a zero, gestisce NaN dove necessario
  • ~:* esegue il backup dell'interpretazione dell'argomento per riutilizzare l'input
  • ~r stampa il numero come una stringa di parole inglesi, come richiesto, tranne per la punteggiatura corretta

Campione:

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

192hqfwoelkqhwef9812ho1289hg18hoif3h1o98g3hgq
NaN

Informazioni su Lisp principalmente da Practical Common Lisp .

Modifica, giocato correttamente fino a 56 caratteri

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

Questa versione funziona in modo piuttosto diverso. Invece di leggere una riga e convertirla, invoca il lettore lisp a interpretare l'input come espressione lisp s, tenta di usarlo come numero e, se vengono prodotti errori, li ignora producendo zero per alimentare la stringa di formato condizionale. Questa potrebbe essere la prima volta che ho visto di lisp produrre un programma davvero conciso ... Divertimento!

  • (read) Richiama il lettore / parser lisp per leggere un'espressione dall'input standard e convertirla in un oggetto appropriato
  • (floor) tenta di convertire qualsiasi tipo numerico nel numero intero inferiore più vicino, i tipi non numerici generano un errore
  • (ignore-errors ...) fa quello che dice sulla latta, cattura e ignora qualsiasi errore nell'espressione racchiusa, restituendo zero per alimentare il ramo NaN della stringa di formato

Non è certo un problema che la vecchia domanda :) Ho modificato la tua risposta per includere il nome della lingua e il conteggio dei caratteri in un'intestazione.
Programma FOX il

Grazie per le modifiche, non ho ancora ottenuto la sintassi Stack * per queste cose. Sono tornato indietro e ho risolto un errore che ho fatto anche nella descrizione del condizionale nella stringa di formato.
Tom Scogland,

3

PHP, 327 310 308 byte

<?$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;

accetta il numero come parametro, funziona per 0 <= n <= 12999

abbattersi

// 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
;

2

SAS, 70 caratteri

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

Le istruzioni windowe displayaprono il prompt dei comandi SAS. L'immissione per nva alla riga 1. Questo sfrutta il formato SAS words.che stamperà il numero come una parola o una serie di parole con "e", "" e "-" come appropriato.


2

PHP

777 caratteri

Questo è sicuramente un tentativo terribile, ma non puoi accusarmi di approfittare di eventuali scappatoie, inoltre è un numero molto fortunato. Grazie a ProgramFOX per l'informazione.

<?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 lunga

<?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]];}
}

1
Penso che si possa ridurre il codice per la creazione di array come questo: array('zero','one','two').
Programma FOX il

@ProgramFOX o anche ['zero','one','two'](php 5.4+). E se non ti dispiace E_NOTICE, [zero,one,two]funzionerebbe anche.
primo

Dovrei aggiornarlo, ma 777 è un numero così fortunato.
Oca,

+1 per i tuoi sforzi. PHP è tragicamente sottorappresentato nel codice golf.
primo

1

Python 2.x - 378

Derivata della risposta delle lucciole, anche se cambiando Pper includere milioni o trilioni, ecc. Potrebbe ricorsivamente essere usata per qualsiasi intervallo di numeri positivi. Questo supporta anche valori fino a 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())

Test di esempio (input è <<<, output è >>>):

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

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

Anche se, se qualcuno può spiegare questo strano problema di "buffer underflow" che ho, sarebbe bello ...

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

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

print divmod(-2,1000) #-> (-1, 998)
primo

Oh, certo. Stavo pensando che potrebbe valere un valore assoluto o qualcosa del genere. Ma c'è -1*1000e un "resto" di 998.

1

SmileBASIC, 365 Trecentoquarantasette byte

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

C'è uno spazio finale se l'ultima o due cifre sono 0.


0

MOO - 55 caratteri

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

Oppure, se non ho bisogno di stampare su "stdout" - 42 caratteri: $string_utils:english_number(read(player))

Nota: questo codice non stampa alcun prompt sull'output standard e stampa zeroinvece diNaN quando l'input non è un numero.

Come bonus, questo codice può gestire qualsiasi numero entro i limiti della lingua moo ( 2147483647- -2147483648).


0

Wolfram Language 27 40 byte

Facendo uso della funzione nativa, IntegerName,

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

Quanto sopra richiede l'input dell'utente. La presente implementazione restituisce "NaN" se l'utente inserisce qualcosa di diverso da un numero intero.


Alcuni esempi (con ingressi preimpostati) :

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

duecentoquarantatre


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

un miliardo, duecentotrentaquattro milioni, cinquecentosessantasette, ottocentonovanta


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

NaN


0

Python 2 , 333 byte

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)))

Provalo online!

Questo va da 1 a 999.999 inclusi.


0

Pyth, 239 242 byte

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

L'input è un numero intero nell'intervallo [0-999.999]. Provalo online qui . Spiegazione in sospeso.

Versione precedente, operazione molto simile, ma non supporta 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

Spiegazione della versione precedente:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.