Konwertuj język angielski na liczbę bez wbudowanych bibliotek i bibliotek

14

To wyzwanie jest podobne do tego drugiego , jednak wprowadziłem ograniczenie (patrz pogrubiony tekst poniżej), które moim zdaniem uczyniłoby to znacznie trudniejszym i (mam nadzieję) dobrą zabawę.

Wyzwanie

Napisz program lub funkcję w dowolnym języku programowania, który przyjmuje jako dane wejściowe angielską nazwę dodatniej liczby całkowitej nnieprzekraczającej 100i zwraca njako liczbę całkowitą.

Standardowe luki są zabronione i nie można używać żadnych wbudowanych funkcji, narzędzi zewnętrznych ani bibliotek, które już wykonują to zadanie .

Najkrótszy kod źródłowy w bajtach wygrywa.

Test

Tutaj wszystkie input->outputprzypadki:

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
Kok
źródło
1
A co z wbudowanym urządzeniem wykonującym połowę zadania, na przykład znajdowaniem nazwy Unicode punktu kodowego.
Brad Gilbert b2gills
@ BradGilbertb2gills Nie, to nie jest w porządku.
Bob

Odpowiedzi:

22

C, 160 bajtów

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

Sprawdź to

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

Jak to działa

Po kilku próbach, znalazłem funkcję, która odwzorowuje "wyjątkowe" numery 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, do znaków ASCII k, ., [, <, *, , c, K, w, y, e, (, S, _, -, C, ), 7, =, 4, &,o, ], s, Y, g, m, N, Odpowiednio.

Ta funkcja to:

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

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

    return r%45+77;
}

Program w golfa oblicza hashfunkcję wejścia, dopóki nie osiągnie końca łańcucha lub znaku -. Następnie przeszukuje skrót w ciągu k.[<* cKwye(S_-C)7=4&o]sYgmNi określa odpowiednią liczbę. Jeśli osiągnięto koniec ciągu wejściowego, zwracana jest liczba, jeśli zamiast tego -osiągnięto a, to zwracana jest liczba plus wynik programu gry w golfa zastosowanego do reszty ciągu wejściowego.

Kok
źródło
Myślę, że gdyby istniała wersja C gry w golfa, mogłaby faktycznie pokonać języki takie jak CJam Pyth Japt itp.
busukxuan
11

JavaScript (ES6), 175 166 163 156 153 147 bajtów

Zaoszczędź 7 bajtów dzięki @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``

Sprawdź to tutaj:

Jak to działa

Podstawową ideą jest podzielenie każdej liczby na słowa cyfrowe, a następnie odwzorowanie każdego słowa na odpowiednią cyfrę. Prawie wszystkie słowa są ustawione tak, aby były odpowiednio dopasowane za pomocą prostego wyrażenia regularnego, ale istnieje kilka anomalii:

  • elevenprzez nineteen: jeśli słowo zawiera el, lub a tew środku (aby uniknąćten ), dodajemy on-na początku znak , zmieniając je na „ on-elevenprzez” on-nineteen.
  • twenty, thirtyItp .: zastąpienie końcowego znaku yze -dzmiany tetwent-d , thirt-ditd

Teraz dzielimy się na łączniki, spacje i drs. Dzieli to wszystko od 11 do 99 na odpowiadające im słowa cyfrowe i"one hundred" na [one,hun,ed]. Następnie mapujemy każde z tych słów za pomocą tablicy wyrażeń regularnych i zachowujemy indeks tego, który pasuje jako pierwszy.

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.

Do tej pory każde wejście będzie tablicą odpowiednich cyfr. Wszystko, co musimy zrobić, to dołączyć do nich join``, przekonwertować na liczbę z jednostką +, i gotowe.

ETHprodukcje
źródło
Proszę wytłumacz.
Bob
@ Bob Pewnie, dodano wyjaśnienie.
ETHprodukcje
Nie .findIndex(y=>x.match(y))działa?
Neil,
@ Neil Nie zdawałem sobie z tego sprawy, ale tak się dzieje, dzięki!
ETHprodukcje
Jestem prawie pewien, że potrafisz pseudonim replace.
Mama Fun Roll
6

sh + coreutils, 112 bajtów

Może być uruchamiany na wszystkich testach jednocześnie, po jednym na linię.

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

Wyjaśnienie

Backticked awkocenia sedskrypt

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

który przekształca części liczb w ich reprezentację numeryczną.

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

Dodatkowe wiersze skryptu sed

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

zająć się -tys i one hundred.

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

Na koniec usuń wiodące +s i wszystko, co nie jest +, *lub cyfrę.

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

Pozostają tylko wyrażenia matematyczne

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

i może być wpuszczony bc.

Rainer P.
źródło
4

Pyth, 79 76 75 68 bajtów

Dziękujemy @ETHproductions za 7 bajtów.

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

Zasadniczo najpierw sprawdza przypadek narożny 100, a następnie używa tablicy pierwszych dwóch liter liczb od 0 do 11, aby określić semantykę wejścia i zmodyfikować wartość zgodnie z sufiksem („-ty” i „-teen”; ” lv ”w 12 to kolejny przypadek narożny). Najpierw dzieli dane wejściowe na listę słów, a następnie mapuje każde z nich na wartość i sumuje je.

W pythonowym pseudokodzie:

                           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

Zestaw testowy


Python 3, 218 bajtów

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

Zasadniczo identyczny z odpowiedzią na Pyth.


Poza tematem:

Właśnie odkryłem sensowną wersję odpowiedzi na życie, wszechświat i wszystko: to spragnione herbaty gałązki. Wow, gałązki tęsknią za herbatą! Nie jestem pewien, ile innych odpowiedzi to robi, ale dla mojej odpowiedzi, jeśli wejście to „spragniony herbaty”, wynik to 42.

busukxuan
źródło
Wierzę, że możesz zaoszczędzić siedem bajtów, używając spakowanego ciągu . Skopiuj wyjście i umieść je w miejscu "ontwthfofisiseeiniteel"tego programu.
ETHprodukcje
@ETHproductions Wow, dzięki! Ostatnim razem, gdy sprawdzałem, na początku sznurka wciąż było „ze”, a pakowanie nie mogło działać. Nie sprawdziłem jeszcze raz po tym, jak grałem w golfa.
Jeszcze
@ETHproductions tak, faktycznie to zrobiłem, jest to pseudokod.
busukxuan
2

Python 3, 365 361 310 303 znaków

Grał w golfa

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

Nie golfił

 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
źródło
45 znaków krótszy: 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(",")Ale jak widzę, powinien działać bez przypisywania go do zmiennej n, wystarczy wywołać .index()bezpośrednio na niej.
manatwork
7 znaków krótsze: "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
Silnik witryny StackExchange ma irytujący nawyk: wstawia niewidoczne znaki (U200C Zero Width Non-Joiner i U200B Zero Width Space) do kodu zamieszczonego w komentarzach. Też je skopiowałeś. Zredagowałem twój post, aby je usunąć.
manatwork
2

Haskell, 252 231 bajtów

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

Spowoduje to utworzenie listy wszystkich angielskich nazw liczb od „jeden” do „dziewięćdziesiąt dziewięć”, a następnie przeglądanie indeksu danych wejściowych w górę. Jeśli nie istnieje, to w przypadku krawędzi sto „sto”, więc zwraca 100, w przeciwnym razie zwróci indeks.

Nie golfił

-- 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
źródło
2

Python 2, 275 znaków

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

Po prostu buduje listę każdej liczby i znajduje indeks.

Piotr
źródło
1

Japt, 82 bajty

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

Każda ¿reprezentuje niezadrukowany znak. Przetestuj online!

Na podstawie mojej odpowiedzi JS. Odejmij jeden bajt, jeśli wynik nie musi być liczbą całkowitą, ponieważ wyglądałby dokładnie tak samo jak łańcuch.

Jak to działa

+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
ETHprodukcje
źródło
1

JavaScript, 214 199 bajtów

Jak zawsze: okazuje się, że jest to zbyt długo, aby konkurować, ale teraz, kiedy skończyłem, marnowanie czasu na publikowanie tego byłoby marnotrawstwem.

Być może istnieje oczywisty sposób na grę w golfa, który przeoczyłem?

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 dla przypadków testowych

vvye
źródło
1
Jak o zmieniających fsię 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:''))? Ponadto do funkcji takiej można przekazać argument o jednym łańcuchu:s.indexOf`lv`
ETHproductions
@ETHproductions To świetnie, dziękuję! Nie wiedziałem, że JS ma przecinek, a skrót do przekazywania ciągu znaków jest również bardzo przydatny.
vvye
1

Perl, 158 bajtów

@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

Działa z wiersza poleceń. one hundrednależy wprowadzić w taki sposób, "one hundred"aby nie interpretować go jako dwóch danych wejściowych.

CJ Dennis
źródło