Konversi Bahasa Inggris ke angka tanpa built-in atau perpustakaan

14

Tantangan ini mirip dengan yang lain ini , namun saya membuat batasan (lihat teks tebal di bawah) yang menurut saya akan membuatnya jauh berbeda dan (saya harap) juga menyenangkan.

Tantangan

Tulis program atau fungsi dalam bahasa pemrograman apa pun yang menggunakan input bahasa Inggris dari bilangan bulat positif yang ntidak melebihi 100dan kembali nsebagai bilangan bulat.

Celah standar dilarang dan Anda tidak bisa menggunakan fungsi bawaan, alat eksternal, atau pustaka yang sudah melakukan pekerjaan ini .

Kode sumber terpendek dalam byte menang.

Uji

Di sini semua input->outputkasus:

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
Bob
sumber
1
Bagaimana dengan built-in yang melakukan setengah pekerjaan, misalnya menemukan nama unicode dari codepoint.
Brad Gilbert b2gills
@ BradGilbertb2gills Tidak, ini tidak baik.
Bob

Jawaban:

22

C, 160 byte

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

Menguji

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

Bagaimana itu bekerja

Setelah beberapa kali mencoba, saya menemukan fungsi yang memetakan "luar biasa" nomor 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, dengan karakter ASCII yang dapat dicetak k, ., [, <, *, , c, K, w, y, e, (, S, _, -, C, ), 7, =, 4, &,o, ], s, Y, g, m, N, Masing-masing.

Fungsi ini adalah:

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

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

    return r%45+77;
}

Program golf menghitung hashfungsi input hingga mencapai akhir string atau karakter -. Kemudian mencari hash dalam string k.[<* cKwye(S_-C)7=4&o]sYgmNdan menentukan angka yang sesuai. Jika akhir dari string input telah mencapai angka dikembalikan, jika sebaliknya sebuah -telah tercapai, maka itu dikembalikan nomor ditambah hasil program golf yang diterapkan ke seluruh string input.

Bob
sumber
Saya berpikir, jika ada versi golf C, itu mungkin benar-benar mengalahkan bahasa seperti CJam Pyth Japt dll ...
busukxuan
11

JavaScript (ES6), 175 166 163 156 153 147 byte

Disimpan 7 byte berkat @Neil

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

Verifikasi di sini:

Bagaimana itu bekerja

Ide dasarnya adalah untuk membagi setiap angka menjadi digit-kata-katanya, lalu memetakan setiap kata ke digit yang sesuai. Hampir semua kata diatur untuk dicocokkan dengan benar dengan regex sederhana, tetapi ada beberapa anomali:

  • eleventhrough nineteen: jika kata tersebut mengandung a el, atau a tedi tengah (untuk menghindari ten), kami menambahkan a on-ke awal, mengubahnya menjadi on-elevenlewat on-nineteen.
  • twenty, thirty, Dll .: menggantikan Trailing ydengan -dperubahan ini twent-d, thirt-d, dll

Sekarang kita berpisah pada tanda hubung, spasi, dan drs. Ini membagi semuanya dari 11 menjadi 99 menjadi angka-kata yang sesuai, dan "one hundred"menjadi [one,hun,ed]. Lalu kami memetakan masing-masing kata ini melalui array regex, dan menyimpan indeks yang cocok terlebih dahulu.

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.

Sekarang, setiap input akan menjadi array dari digit yang tepat. Yang harus kita lakukan adalah bergabung dengan mereka join``, mengonversi ke nomor dengan unary +, dan kita sudah selesai.

Produksi ETH
sumber
Tolong jelaskan.
Bob
@ Bob Tentu, penjelasan ditambahkan.
ETHproduksi
Tidak .findIndex(y=>x.match(y))bekerja
Neil
@Neil Aku tidak menyadari itu akan terjadi, tetapi itu terjadi, terima kasih!
ETHproduksi
Saya cukup yakin Anda bisa alias replace.
Mama Fun Roll
6

sh + coreutils, 112 byte

Dapat dijalankan di semua testc sekaligus, satu per baris.

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

Penjelasan

The backticked awkmengevaluasi ke sedskrip

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

yang mengubah bagian-bagian angka menjadi representasi numerik mereka.

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

Baris tambahan skrip sed

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

jaga -tys dan one hundred.

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

Akhirnya, hapus +s dan semua yang bukan +, *atau digit.

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

Hanya ekspresi matematika yang tersisa

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

dan bisa disalurkan ke bc.

Rainer P.
sumber
4

Pyth, 79 76 75 68 byte

Terima kasih @ETHproduk selama 7 byte.

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

Pada dasarnya periksa dulu kasus sudut 100, kemudian gunakan array dari dua huruf pertama dari angka 0 hingga 11 untuk menentukan semantik input dan memodifikasi nilai sesuai dengan akhiran ("-ty" dan "-teen"; " lv "dalam 12 adalah kasus sudut lain). Pertama membagi input menjadi daftar kata, lalu memetakan masing-masing ke nilai, dan jumlahkan.

Dalam pseudocode 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

Suite uji


Python 3, 218 byte

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

Pada dasarnya identik dengan jawaban Pyth.


Diluar topic:

Saya baru saja menemukan versi yang bermakna dari jawaban untuk kehidupan, alam semesta dan segalanya: itu adalah ranting yang haus teh. Wow, ranting yang mendambakan teh! Saya tidak yakin berapa banyak jawaban lain melakukan ini, tetapi untuk jawaban saya jika inputnya adalah "ranting teh-haus" hasilnya adalah 42.

busukxuan
sumber
Saya percaya Anda dapat menyimpan tujuh byte dengan menggunakan string yang dikemas . Salin output dan taruh di tempat "ontwthfofisiseeiniteel"dalam program ini.
ETHproduksi
@ ETProduksi Wow, terima kasih! Terakhir kali saya periksa, masih ada "ze" di bagian atas tali, dan pengepakan tidak bisa. Saya tidak memeriksa sekali lagi setelah saya bermain golf. Sekali lagi, terima kasih xD
busukxuan
@ ETHproductions ya saya benar-benar melakukannya, itu di bawah kodesemu.
busukxuan
2

Python 3, 365 361 310 303 karakter

Golf

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

Tidak disatukan

 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
Argenis García
sumber
45 karakter lebih pendek: 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(",")Tapi seperti yang saya lihat, harus berfungsi tanpa menugaskannya ke variabel n, panggil saja .index()secara langsung.
manatwork
7 karakter lebih pendek: "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
Mesin situs StackExchange memiliki kebiasaan yang menjengkelkan: ia memasukkan karakter yang tidak terlihat (U200C Zero Width Non-Joiner dan U200B Zero Width Space) ke dalam kode yang diposting dalam komentar. Anda menyalin dan menempelkannya juga. Saya mengedit posting Anda untuk menghapusnya.
manatwork
2

Haskell, 252 231 byte

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

Ini membuat daftar semua nama nomor bahasa Inggris dari "satu" ke "sembilan puluh sembilan" dan kemudian melihat indeks input naik. Jika tidak ada, kita ada di tepi kasus "seratus", jadi itu kembali 100, kalau tidak itu akan mengembalikan indeks.

Tidak disatukan

-- 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..]
Zeta
sumber
2

Python 2, 275 karakter

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

Sederhana membangun daftar setiap angka dan menemukan indeks.

Peter
sumber
1

Japt, 82 byte

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

Masing-masing ¿mewakili karakter yang tidak dapat dicetak. Uji secara online!

Berdasarkan jawaban JS saya. Kurangi satu byte jika output tidak perlu berupa bilangan bulat, karena akan muncul persis sama dengan string.

Bagaimana itu bekerja

+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
Produksi ETH
sumber
1

JavaScript, 214 199 byte

Seperti biasa: ternyata ini terlalu lama untuk bersaing, tetapi sekarang setelah saya selesai, akan sia-sia untuk tidak memposting ini.

Mungkin ada cara yang jelas untuk bermain golf sejauh ini yang saya abaikan?

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 untuk kasus uji

ay
sumber
1
Bagaimana mengubah fke 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:''))? Juga, argumen string tunggal dapat dikirimkan ke fungsi seperti:s.indexOf`lv`
ETHproduksi
@ ETHproductions Bagus sekali, terima kasih! Saya tidak tahu JS memiliki operator koma, dan singkatan untuk melintas string juga sangat berguna.
vvye
1

Perl, 158 byte

@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

Berjalan dari baris perintah. one hundredharus dimasukkan "one hundred"untuk menghentikannya ditafsirkan sebagai dua input.

CJ Dennis
sumber