組み込みまたはライブラリなしで英語を数字に変換する


14

この課題は他の課題と似ていますが、制限を設け(下の太字のテキストを参照)、それをかなり異なったものにしたり(楽しい)ようにしたりします。

チャレンジ

n超えない正の整数の英語名を入力として受け取り、整数として100返す任意のプログラミング言語でプログラムまたは関数を記述しますn

標準の抜け穴は禁止されており、この機能を既に実行している組み込み関数、外部ツール、またはライブラリを使用することはできません

バイト単位の最短ソースコードが優先されます。

テスト

ここにすべてのinput->output場合:

one              -> 1
two              -> 2
three            -> 3
four             -> 4
five             -> 5
six              -> 6
seven            -> 7
eight            -> 8
nine             -> 9
ten              -> 10
eleven           -> 11
twelve           -> 12
thirteen         -> 13
fourteen         -> 14
fifteen          -> 15
sixteen          -> 16
seventeen        -> 17
eighteen         -> 18
nineteen         -> 19
twenty           -> 20
twenty-one       -> 21
twenty-two       -> 22
twenty-three     -> 23
twenty-four      -> 24
twenty-five      -> 25
twenty-six       -> 26
twenty-seven     -> 27
twenty-eight     -> 28
twenty-nine      -> 29
thirty           -> 30
thirty-one       -> 31
thirty-two       -> 32
thirty-three     -> 33
thirty-four      -> 34
thirty-five      -> 35
thirty-six       -> 36
thirty-seven     -> 37
thirty-eight     -> 38
thirty-nine      -> 39
forty            -> 40
forty-one        -> 41
forty-two        -> 42
forty-three      -> 43
forty-four       -> 44
forty-five       -> 45
forty-six        -> 46
forty-seven      -> 47
forty-eight      -> 48
forty-nine       -> 49
fifty            -> 50
fifty-one        -> 51
fifty-two        -> 52
fifty-three      -> 53
fifty-four       -> 54
fifty-five       -> 55
fifty-six        -> 56
fifty-seven      -> 57
fifty-eight      -> 58
fifty-nine       -> 59
sixty            -> 60
sixty-one        -> 61
sixty-two        -> 62
sixty-three      -> 63
sixty-four       -> 64
sixty-five       -> 65
sixty-six        -> 66
sixty-seven      -> 67
sixty-eight      -> 68
sixty-nine       -> 69
seventy          -> 70
seventy-one      -> 71
seventy-two      -> 72
seventy-three    -> 73
seventy-four     -> 74
seventy-five     -> 75
seventy-six      -> 76
seventy-seven    -> 77
seventy-eight    -> 78
seventy-nine     -> 79
eighty           -> 80
eighty-one       -> 81
eighty-two       -> 82
eighty-three     -> 83
eighty-four      -> 84
eighty-five      -> 85
eighty-six       -> 86
eighty-seven     -> 87
eighty-eight     -> 88
eighty-nine      -> 89
ninety           -> 90
ninety-one       -> 91
ninety-two       -> 92
ninety-three     -> 93
ninety-four      -> 94
ninety-five      -> 95
ninety-six       -> 96
ninety-seven     -> 97
ninety-eight     -> 98
ninety-nine      -> 99
one hundred      -> 100

1
たとえば、コードポイントのユニコード名を見つけるなど、半分の仕事をするビルトインはどうでしょうか。
ブラッドギルバートb2gills 16

@ BradGilbertb2gillsいいえ、大丈夫ではありません。
ボブ

回答:


22

C、160バイト

g(char*s){char i=1,r=0,*p="k^[#>Pcx.yI<7CZpVgmH:o]sYK$2";for(;*s^'-'&&*s;r+=*s++|9);r=r%45+77;for(;*p!=r;p++,i++);return((*s^'-')?0:g(s+1))+(i<21?i:10*(i-18));}

試して

int main ()
{
    char* w[] = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", "twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three", "thirty-four", "thirty-five", "thirty-six", "thirty-seven", "thirty-eight", "thirty-nine", "forty", "forty-one", "forty-two", "forty-three", "forty-four", "forty-five", "forty-six", "forty-seven", "forty-eight", "forty-nine", "fifty", "fifty-one", "fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six", "fifty-seven", "fifty-eight", "fifty-nine", "sixty", "sixty-one", "sixty-two", "sixty-three", "sixty-four", "sixty-five", "sixty-six", "sixty-seven", "sixty-eight", "sixty-nine", "seventy", "seventy-one", "seventy-two", "seventy-three", "seventy-four", "seventy-five", "seventy-six", "seventy-seven", "seventy-eight", "seventy-nine", "eighty", "eighty-one", "eighty-two", "eighty-three", "eighty-four", "eighty-five", "eighty-six", "eighty-seven", "eighty-eight", "eighty-nine", "ninety", "ninety-one", "ninety-two", "ninety-three", "ninety-four", "ninety-five", "ninety-six", "ninety-seven", "ninety-eight", "ninety-nine", "one hundred"};

    int n;
    for (n = 1; n <= 100; n++)
    {
        printf ("%s -> %d\n", w[n], g(w[n]));
        if (n != g(w[n]))
        {
            printf ("Error at n = %d", n);
            return 1;
        }
    }
    return 0;
}

使い方

いくつかの試みの後、私は"例外"の数字をマップする機能を発見したonetwothreefourfivesixseveneightnineteneleventwelvethirteenfourteenfifteensixteenseventeeneighteennineteentwentythirtyfortyfiftysixtyseventyeightyninetyone hundred、印刷可能なASCII文字にk.[<*cKwye(S_-C)7=4&o]sYgmN、それぞれ。

この関数は次のとおりです。

char hash (char* s)
{
    char r = 0;

    while (*s)
    {
        r += *s|9;
        s++;
    }

    return r%45+77;
}

ゴルフプログラムhashは、文字列または文字の最後に到達するまで入力の関数を計算します-。次に、文字列内のハッシュを検索しk.[<* cKwye(S_-C)7=4&o]sYgmN、対応する番号を決定します。入力文字列の最後に到達した場合は数値が返され、代わりにa -に到達した場合は、数値と入力文字列の残りに適用されたゴルフプログラムの結果が返されます。


私は... Cのゴルフのバージョンがあった場合、それが実際にCJam Pyth JAPTなどのような言語を打つかもしれない、と思っています
busukxuan

11

JavaScriptの(ES6)、175の 166 163 156 153 147バイト

@Neilのおかげで7バイト節約

a=>+a.replace(/.+te|.*el|y$/,x=>x[1]?'on-'+x:'-d').split(/ |-|dr/).map(x=>"un|d,on|le,w,th,fo,f,x,s,h,i,".split`,`.findIndex(y=>x.match(y))).join``

ここで確認してください:

使い方

基本的な考え方は、各数字を数字の単語に分割し、各単語を対応する数字にマッピングすることです。ほとんどすべての単語は、単純な正規表現と適切に一致するように設定されていますが、いくつかの異常があります。

  • eleventhrough nineteen:単語の途中にel、またはが含まれる場合te(を避けるためten)、on-先頭にaを追加し、これらをon-eleventhrough に変更しますon-nineteen
  • twentythirty等:トレーリングを交換yして-d変更これらにtwent-dthirt-d

次に、ハイフン、スペース、およびdrsで分割します。これにより、11から99までのすべてが、対応する数字の単語とに"one hundred"分割され[one,hun,ed]ます。次に、これらの各単語を正規表現の配列にマッピングし、最初に一致したもののインデックスを保持します。

0: /un|d/ - This matches the "hun" and "ed" in 100, as well as the "d" we placed on the end of 20, 30, etc.
1: /on|le/ - Matches "one" and the "on" we placed on the beginning of 11 through 19, along with "eleven".
2: /w/ - Matches "two", "twelve", and "twenty".
3: /th/ - Matches "three" and "thirty".
4: /fo/ - Matches "four" and "forty".
5: /f/ - "five" and "fifty" are the only words by now that contain an "f".
6: /x/ - "six" and "sixty" are the only words that contain an "x".
7: /s/ - "seven" and "seventy" are the only words by now that contain an "s".
8: /h/ - "eight" and "eighty" are the only words by now that contain an "h".
9: /i/ - "nine" and "ninety" are the only words by now that contain an "i".
10: /<empty>/ - "ten" is the only word left, but it still has to be matched.

今では、すべての入力が適切な数字の配列になります。私たちがしなければならないのは、それらを結合しjoin``、単項の数に変換するだけ+です。


説明してください。
ボブ

@Bob Sure、説明を追加。
ETHproductions

動作しません.findIndex(y=>x.match(y))か?
ニール

@Neil私はそれが実現することを理解していませんでしたが、感謝します!
ETHproductions

エイリアスを作成できると確信していますreplace
ママファンロール

6

sh + coreutils、112バイト

1行に1つずつ、すべてのテストケースで一度に実行できます。

sed -r "`awk '$0="s/"$0"/+"NR"/g"'<<<"on
tw
th
fo
fi
si
se
ei
ni
te|lv
el"`
s/ /y0/
s/y/*10/
s/^\+|[a-z-]//g"|bc

説明

バックティックawksedスクリプトに対して評価します

s/on/+1/g       # one, one hundred
s/tw/+2/g       # two, twelve, twenty
s/th/+3/g       # three, thirteen, thirty
s/fo/+4/g       # ...
s/fi/+5/g
s/si/+6/g
s/se/+7/g
s/ei/+8/g
s/ni/+9/g
s/te|lv/+10/g   # ten, -teen, twelve
s/el/+11/g      # eleven

数値の一部を数値表現に変換します。

fife            ->    +5ve
ten             ->    +10n
eleven          ->    +11even
twelve          ->    +2e+10e
sixteen         ->    +6x+10en
thirty-seven    ->    +3irty-+7ven
forty-four      ->    +4rty-+4ur
eighty          ->    +8ghty
one hundred     ->    +1e hundred

sedスクリプトの追加行

s/ /y0/
s/y/*10/

の世話を-tyone hundredます。

+3irty-+7ven    ->    +3irt*10-+7ven
+4rty-+4ur      ->    +4rt*10-+4ur
+8ghty          ->    +8ght*10
+1e hundred     ->    +1ey0hundred      ->    +1e*100hundred

最後に、先頭+のsおよび以外のすべて+*または数字を削除します。

s/^\+|[a-z-]//g"

数式のみが残ります

fife            ->    5
sixteen         ->    6+10
forty-four      ->    4*10+4
eighty          ->    8*10
one hundred     ->    1*100

およびにパイプすることができますbc


4

Pyth、79 76 75 68バイト

7バイトの@ETHproductionsに感謝します。

?}"hu"z100sm*+hxc."ewEСBu­["2<d2?|}"een"d}"lv"dTZ?}"ty"dT1cz\-

基本的に最初に100のコーナーケースをチェックし、次に0〜11の数字の最初の2文字の配列を使用して入力のセマンティクスを決定し、サフィックス( "-ty"および "-teen"; " 12のlv "は別のコーナーケースです)。最初に入力を単語のリストに分割し、次に各単語を値にマッピングして合計します。

pythonic擬似コードの場合:

                           z = input()    # raw, unevaluated
                           Z = 0
                           T = 10
?}"hu"z                    if "hu" in z:  # checks if input is 100
  100                        print(100)
                           else:
sm                           sum(map( lambda d: # evaluates each word, then sum
  *                            multiply(
   +hxc."ewEСBu­["2<d2           plusOne(chop("ontwth...niteel",2).index(d[:2])) + \
                                 # chops string into ["on","tw",..."el"]
                                 # ."ewEСBu­[" is a packed string
     ?|}"een"d}"lv"dTZ               (T if "een" in d or "lv" in d else Z),
                                     # add 10 for numbers from 12 to 19
   ?}"ty"dT1                     T if "ty" in d else 1),  # times 10 if "-ty"
  cz\-                         z.split("-"))  # splits input into words

テストスイート


Python 3、218バイト

z=input()
if "hu" in z:print(100);exit()
print(sum(map(lambda d:([0,"on","tw","th","fo","fi","si","se","ei","ni","te","el"].index(d[:2])+(10 if "een" in d or "lv" in d else 0))*(10 if "ty" in d else 1),z.split("-"))))

Pythの回答と基本的に同じです。


オフトピック:

私は、人生、宇宙、すべてに対する答えの意味のあるバージョンを発見しました。それはお茶に飢えた小枝です。うわー、お茶に憧れる小枝!これを行う他の回答の数はわかりませんが、私の回答では、入力が「tea-thirsty-twigs」の場合、出力は42です。


パックされた文字列を使用すると、7バイト節約できます。出力をコピーして"ontwthfofisiseeiniteel"、このプログラムの代わりに配置します。
ETHproductions

@ETHproductionsわあ、ありがとう!前回チェックしたとき、文字列の先頭にはまだ「ze」があり、パッキングは機能しませんでした。ゴルフをした後、もう一度チェックしませんでした。繰り返しますが、おかげでxD
busukxuan

@ETHproductionsはい、私は実際にそうしました、それは擬似コードの下にあります。
-busukxuan

2

Python 3、365 361 310 303文字

ゴルフ

def f(a):
 y=0
 for i in a.split("-"):
  x="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",").index(i)
  y+=x+1 if x<20 else range(30,110,10)[x-20]
 return y

非ゴルフ

 def nameToNumber (numberName):
    names = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen",
             "fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","forty","fifty",
             "sixty","seventy","eighty","ninety","one hundred"]
    numbers = range(30, 110, 10)
    number = 0
    for n in numberName.split("-"):
        x = names.index(n)
        number += x + 1 if x < 20 else numbers[x - 20]
    return number

45文字より短い:n="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".split(",")しかし、私が見るように、変数nに代入せずに機能するはずで、.index()直接呼び出します。
-manatwork

7文字より短い:"one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",")
manatwork

StackExchangeサイトエンジンにはいらいらする癖があります。コメントに投稿されたコードに不可視の文字(U200Cゼロ幅の非ジョイナーおよびU200Bゼロ幅のスペース)を挿入します。あなたもそれらをコピー&ペーストしました。投稿を編集して削除しました。
マナトワーク

2

ハスケル、 252 231バイト

let l=words;k=l"six seven eight nine";w=l"one two three four five"++k++l"ten eleven twelve"++((++"teen")<$>l"thir four fif"++k)++[n++"ty"++s|n<-l"twen thir for fif"++k,s<-"":['-':x|x<-take 9w]]in maybe 100id.flip lookup(zip w[1..])

これにより、「1」から「ninety-nine」までのすべての英語の番号名のリストが作成され、入力のインデックスが検索されます。存在しない場合、「100」というエッジケースにあるため、を返します100。そうでない場合は、インデックスを返します。

非ゴルフ

-- k in the golfed variant
common = words "six seven eight nine" 

-- w in the golfed variant
numbers = words "one two three four five" ++ common
       ++ words "ten eleven twelve" ++ [p ++ "teen" | p <- words "thir four fif" ++ common]
       ++ [p ++ "ty" ++ s| p <- words "twen thir for fif" ++ common
                         , s <- "" : map ('-':) (take 9 numbers)]

-- part of the expression in the golfed variant
convert :: String -> Int
convert s = maybe 100 id $ lookup s $ zip numbers [1..]

2

Python 2、275文字

def x(n):a='one two three four five six seven eight nine ten eleven twelve'.split();t='twen thir four fif six seven eigh nine'.split();b=[i+'teen'for i in t[1:]];c=[i+'ty'for i in t];return(a+b+[i+j for i in c for j in ['']+['-'+k for k in a[:9]]]+['one hundred']).index(n)+1

すべての番号のリストを簡単に作成し、インデックスを見つけます。


1

Japt、82バイト

+Ur`(.+)¿``¿-$1` r"y$""-d" q$/ |-|dr/$ £`un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`qi b_XfZ}Ãq

それぞれ¿は、印刷できない文字を表します。オンラインでテストしてください!

JSの回答に基づきます。出力が文字列とまったく同じに見えるため、出力が整数である必要がない場合は、1バイトを減算します。

使い方

+Ur`(.+)¿` `¿-$1`  r"y$""-d" q/ |-|dr/ £  `un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`          qi b_ XfZ}à q
+Ur"(.+)te""on-$1" r"y$""-d" q/ |-|dr/ mX{"un|dioniwo|wenithifoifixisihineiteiniv"qi bZ{XfZ}} q

Ur"(.+)te""on-$1" // Replace "thirteen", "fourteen", etc. with "on-thiren", "on-fouren", etc.
r"y$""-d"         // Replace "twenty", "thirty", etc. with "twent-d", "thirt-d", etc.
q/ |-|dr/         // Split at occurances of a space, hyphen, or "dr". By now,
                  // "one", "thirteen", "twenty", "sixty-six", "one hundred" will have become:
                  // "one", "on" "thiren", "twent" "d", "sixty" "six", "one" "hun" "ed"
mX         }      // Map each item X in the resulting array to:
"..."qi           //  Take this string, split at "i"s,
b_XfZ}            //  and find the first item Z where X.match(RegExp(Z)) is not null.
                  //  See my JS answer to learn exactly how this works.
                  // Our previous example is now
                  // "1", "1" "3", "2" "0", "6" "6", "1" "0" "0"
+              q  // Join and convert to integer.
                  // 1, 13, 20, 66, 100

1

JavaScript、214 199バイト

いつものように、これは競争するには長すぎますが、これで完了したので、これを投稿しないのは無駄です。

おそらく私が見落としていた、これをさらにゴルフする明らかな方法がありますか?

e=s=>s.slice(-1)=='d'?100:'  ontwthfofisiseeinite'.indexOf(s.slice(0,2))/2;f=s=>([t,u]=s.split('-'),~s.indexOf`le`?11:~s.indexOf`lv`?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))

テストケース用のJSFiddle


1
への変更ff=s=>([t,u]=s.split('-'),~s.indexOf('le')?11:~s.indexOf('lv')?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))どうですか?また、次のような関数に単一の文字列引数を渡すことができますs.indexOf`lv`
。– ETHproductions

@ETHproductionsそれは素晴らしい、ありがとう!JSにコンマ演算子があることは知りませんでしたが、文字列の受け渡しの短縮形も非常に便利です。
vvye

1

Perl、158バイト

@s=split/(\d+)/,'te1ten0l1le1on1tw2th3fo4fi5si6se7ei8ni9d00';foreach(split'-',$n=$ARGV[0]){for($i=0;$i<$#s;$i+=2){m/$s[$i]/&&print$s[$i+1]}}$n=~/ty$/&&print 0

コマンドラインから実行します。2つの入力として解釈さone hundredれないように入力する必要があります"one hundred"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.