Преобразование целых чисел в английские слова

21

Целью этого гольф-кода является преобразование целых чисел в английские слова.

Программа запрашивает ввод. Если этот ввод не является целым числом, выведите NaN. Если это целое число, преобразуйте его в английские слова и напечатайте эти слова. Минимальный вход: 0 (ноль). Максимальный ввод: 9000 (девять тысяч).
Итак, 5возвращает five(регистр не имеет значения) и 500возвращает five hundredили five-hundred(тире не имеет значения).

Некоторые другие правила:

A onebefore hundredили thousandявляется необязательным: one hundredэто правильно, но hundredтоже (если ввод 100конечно).

Слово andв к примеру one hundred and forty fiveтоже необязательно.

Пробелы имеют значение. Так что 500, five-hundredили five hundredправильно, но fivehundredэто не так.

Удачи!

ProgramFOX
источник
Здесь есть неутешительный ответ rgagnon.com/javadetails/java-0426.html .
Этот ответ в SO делает подобные вещи, но не код-гольф.
ST3

Ответы:

7

Perl 281 байт

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

Новые строки добавлены для горизонтального здравомыслия. Вышеприведенное может быть использовано в интерактивном режиме или путем передачи значения через stdin.

Работает корректно для всех целочисленных значений в диапазоне [0, 19999] , значения вне этого диапазона демонстрируют неопределенное поведение. Нецелочисленные значения будут усечены до нуля, и поэтому будут сообщаться только значения, которые действительно не числовые NaN.

Пример использования:

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

Пример вывода:

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: тысяча»? И не должны ли 17,2 печатать «NaN»?
DavidC
5
@DavidCarraher "... значения за пределами этого диапазона демонстрируют неопределенное поведение .NaN
Примо
Я не эксперт по Perl, поэтому я задаю этот вопрос: эта программа запрашивает ввод?
ProgramFOX
@ProgramFOX Я обновил его, чтобы читать значение из стандартного ввода (если он выполняется в интерактивном режиме, он запросит у пользователя значение), а не как функцию.
Примо
13

JavaScript (375)

Вероятно, ужасная попытка, но в любом случае, здесь идет ...

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

Довольно напечатано (как функция):

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
}

Пример преобразования (обратите внимание, что он даже выводит, NaNкогда выходит за пределы, то есть неверный ввод):

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это довольно сложно сделать лучше на таком языке, как JavaScript. (вы можете удалить пробел, N(s,z) {returnчтобы сохранить 1 символ)
Math Chiller
О, ха-ха, должно быть, пропустил это. Я также, кажется, пропустил кучу символов в Oстроке. Я исправлю это ..
FireFly
11

Mathematica 60 57

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

Использование:

f[500]

пятьсот

Редактировать:

InputString[]~WolframAlpha~{{"NumberName", 1}, "Plaintext"}
alephalpha
источник
3
Это на самом деле не отвечает на вопрос. Я сказал, что пользователь должен ввести число (используя, например, командную строку или окно приглашения), а затем ваша программа должна вывести слова (например, в командной строке или в окне сообщения). Ваш код - это просто функция для его преобразования, а ваша программа не запрашивает ввод.
ProgramFOX
@ProgramFOX говорит: «Пользователь что-то вводит». Это не означает «Программа запрашивает ввод».
MrZander
@MrZander: Ну, на самом деле я имел в виду «программа запрашивает ввод». Я обновляю свой вопрос, но, конечно, было бы несправедливо, если бы я не проголосовал против ответа алефальфа, поэтому он получил мой +1
ProgramFOX
8

Лисп, 72 56 знаков

Я понимаю, 1), что это старо, и 2) что оно полностью полагается на работу стандартной библиотеки, но тот факт, что вы можете заставить систему печати c-lisp делать такие вещи, всегда меня поражал. Кроме того, это фактически принимает входные данные от пользователя, конвертирует их и распечатывает.

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

Всего 72 символа.

  • :junk-allowed заставляет parse-integer возвращать ноль при ошибке, а не выдавать ошибку.
  • ~:[if-nil~;if-non-nill] условно основывается на нуле, обрабатывает NaN, где это необходимо
  • ~:* резервное копирование интерпретации аргумента для повторного использования ввода
  • ~r печатает число в виде строки английского слова по запросу, за исключением случаев с точной пунктуацией

Образец:

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

192hqfwoelkqhwef9812ho1289hg18hoif3h1o98g3hgq
NaN

Информация о Лиспе в основном из Практического Общего Лиспа .

Редактировать, правильно играть в гольф до 56 символов

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

Эта версия работает довольно по-другому. Вместо того, чтобы читать строку и преобразовывать ее, он вызывает считыватель lisp для интерпретации ввода как s-выражения lisp, пытается использовать его как число, и, если возникают какие-либо ошибки, игнорирует их, генерируя nil для подачи условной строки формата. Это может быть первый случай, когда я видел, что lisp создает действительно краткую программу ... Забавно!

  • (read) Вызывает считыватель / анализатор lisp для чтения одного выражения из стандартного ввода и преобразования его в соответствующий объект
  • (floor) пытается преобразовать любой числовой тип в ближайшее нижнее целое число, нечисловые типы вызывают ошибку
  • (ignore-errors ...) делает то, что говорит на жестяной панели, он ловит и игнорирует любые ошибки во вложенном выражении, возвращая nil для подачи ветви NaN строки формата
Том Скогланд
источник
Это, конечно, не проблема, что вопрос старый :) Я отредактировал ваш ответ, включив в заголовок название языка и количество символов.
ProgramFOX
Спасибо за изменения, я еще не получил синтаксис Stack * для этих вещей. Вернулся и исправил ошибку, которую я сделал в описании условия в строке формата.
Том Скотланд
3

PHP, 327 310 308 байт

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

принимает число в качестве параметра, работает для 0 <= n <= 12999

сломать

// 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
источник
2

SAS, 70 знаков

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

Операторы windowand displayоткрывают командную строку SAS. Ввод для nидет в строке 1. Это использует формат SAS, words.который будет печатать число в виде слова или серии слов с «и», «» и «-» в зависимости от ситуации.

Алекс А.
источник
2

PHP

777 символов

Это определенно ужасная попытка, но вы не можете обвинить меня в использовании каких-либо лазеек, плюс это очень удачное число. Спасибо ProgramFOX за подсказку.

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

Длинная рука

<?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
Я думаю , что вы можете сократить свой код, создавая массивы , как это: array('zero','one','two').
ProgramFOX
@ProgramFOX или даже ['zero','one','two'](php 5.4+). И если ты не возражаешь E_NOTICE, это [zero,one,two]тоже сработает.
Примо
Я должен обновить его, но 777 - такое счастливое число.
Гусь
+1 за ваши усилия. PHP трагически недопредставлен в коде гольф.
Примо
1

Python 2.x - 378

Производное ответа от Fireflys, хотя, если Pвключить миллион или триллионы и т. Д., Его можно рекурсивно использовать для любого диапазона положительных чисел. Это также поддерживает значения до 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())

Пример теста (вход есть <<<, выход есть >>>):

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

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

Хотя, если бы кто-то мог объяснить эту странную проблему «переполнения буфера», это было бы здорово ...

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

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

источник
print divmod(-2,1000) #-> (-1, 998)
Примо
О Конечно. Я думал, что это может принять абсолютную ценность или что-то. Но есть -1*1000и «остаток» 998.
1

SmileBASIC, 365 триста сорок семь байтов

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

Есть пробел, если последние одна или две цифры равны 0.

12Me21
источник
0

MOO - 55 символов

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

Или, если мне не нужно печатать на «стандартный вывод» - 42 символа: $string_utils:english_number(read(player))

Примечание: этот код не выводит подсказки на стандартный вывод и печатает zeroвместо NaNввода, когда это не число.

В качестве бонуса этот код может обрабатывать любое число в границах языка му ( 2147483647- -2147483648).

pppery
источник
0

Wolfram Language 27 40 байтов

Используя нативную функцию IntegerName,

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

Вышеуказанные запросы для ввода пользователя. Настоящая реализация возвращает «NaN», если пользователь вводит что-либо кроме целого числа.


Некоторые примеры (с предустановленными входами) :

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

двести сорок три


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

один миллиард двести тридцать четыре миллиона пятьсот шестьдесят семь тысяч восемьсот девяносто


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

NaN

DavidC
источник
0

Python 2 , 333 байта

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

Попробуйте онлайн!

Это хорошо от 1 до 999 999 включительно.

Час Браун
источник
0

Pyth, 239 242 байта

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

Ввод представляет собой целое число в диапазоне [0-999,999]. Попробуйте это онлайн здесь . Объяснение в ожидании.

Предыдущая версия, очень похожая операция, но не поддерживает 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

Объяснение предыдущей версии:

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
источник