Konvertieren Sie Englisch in eine Zahl ohne integrierte oder Bibliotheken


14

Diese Herausforderung ähnelt der anderen , aber ich habe eine Einschränkung (siehe fettgedruckten Text unten) vorgenommen, die meiner Meinung nach zu großen Unterschieden geführt hat und (ich hoffe) auch Spaß macht.

Die Herausforderung

Schreibe ein Programm oder eine Funktion in jeder Programmiersprache , die die englische Bezeichnung der eine positive ganze Zahl als Eingabe nnicht übersteigt 100und kehrt nals Integer.

Standardlücken sind verboten und Sie können keine eingebauten Funktionen, externen Tools oder Bibliotheken verwenden, die diese Aufgabe bereits erfüllen .

Kürzester Quellcode in Bytes gewinnt.

Prüfung

Hier alle input->outputFälle:

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
Was ist mit einem eingebauten System, das die Hälfte der Arbeit erledigt, zum Beispiel das Finden des Unicode-Namens eines Codepunkts?
Brad Gilbert b2gills

@ BradGilbertb2gills Nein, es ist nicht in Ordnung.
Bob

Antworten:


22

C 160 Bytes

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

Probier es aus

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

Wie es funktioniert

Nach einigen Versuchen, fand ich eine Funktion, die die "außergewöhnlichen" Zahlen abbildet 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, auf die druckbaren ASCII - Zeichen k, ., [, <, *, , c, K, w, y, e, (, S, _, -, C, ), 7, =, 4, &,o, ], s, Y, g, m, N, Respectively.

Diese Funktion ist:

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

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

    return r%45+77;
}

Das Golfprogramm berechnet die hashFunktion der Eingabe, bis das Ende der Zeichenfolge oder des Zeichens erreicht ist -. Dann durchsucht es den Hash in der Zeichenfolge k.[<* cKwye(S_-C)7=4&o]sYgmNund bestimmt die entsprechende Nummer. Wenn das Ende der Eingabezeichenfolge erreicht wurde, wird die Nummer zurückgegeben. Wenn stattdessen a -erreicht wurde, wird die Nummer plus das Ergebnis des Golfprogramms zurückgegeben, das auf den Rest der Eingabezeichenfolge angewendet wird.


Ich denke, wenn es eine Golf-Version von C gäbe, könnte sie Sprachen wie CJam Pyth Japt usw. schlagen ...
busukxuan

11

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

7 Bytes dank @Neil gespart

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

Überprüfen Sie es hier:

Wie es funktioniert

Die Grundidee ist, jede Zahl in ihre Ziffernwörter aufzuteilen und dann jedes Wort der entsprechenden Ziffer zuzuordnen. Fast alle Wörter sind so eingerichtet, dass sie mit einem einfachen regulären Ausdruck richtig übereinstimmen, aber es gibt ein paar Anomalien:

  • elevendurch nineteen: Wenn das Wort ein eloder ein tein der Mitte enthält (um dies zu vermeiden ten), fügen wir on-am Anfang ein hinzu und ändern diese in on-elevendurch on-nineteen.
  • twenty, thirtyUsw .: ein abschließendes Ersetzen ymit -dÄnderungen diese twent-d, thirt-detc.

Jetzt teilen wir uns in Bindestriche, Leerzeichen und drs. Dies teilt alles von 11 bis 99 in die entsprechenden Ziffernwörter und "one hundred"in [one,hun,ed]. Dann ordnen wir jedes dieser Wörter einer Reihe von Regexen zu und behalten den Index desjenigen bei, der zuerst übereinstimmt.

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.

Inzwischen ist jeder Eingang das Array der richtigen Ziffern. Alles, was wir tun müssen, ist sich ihnen anzuschließen join``, in eine unäre Zahl umzuwandeln +, und wir sind fertig.


Bitte erkläre.
Bob

@ Bob Sicher, Erklärung hinzugefügt.
ETHproductions

Nicht .findIndex(y=>x.match(y))funktioniert?
Neil

@Neil Ich wusste nicht, dass würde, aber es tut, danke!
ETHproductions

Ich bin mir ziemlich sicher, dass Sie Alias ​​können replace.
Mama Fun Roll

6

sh + coreutils, 112 Bytes

Kann auf allen Testfällen gleichzeitig ausgeführt werden, einer pro Zeile.

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

Erläuterung

Das Backticked awkwertet das sedSkript aus

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

Dadurch werden Teile von Zahlen in ihre numerische Darstellung umgewandelt.

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

Die zusätzlichen Zeilen des sed-Skripts

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

kümmere dich um -tys und one hundred.

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

Schließlich entfernt führende +s und alles, was nicht ist +, *oder eine Ziffer.

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

Es bleiben nur mathematische Ausdrücke

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

und kann eingespeist werden bc.


4

Pyth, 79 76 75 68 Bytes

Vielen Dank an @ETHproductions für 7 Bytes.

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

Grundsätzlich prüft man zuerst den Eckfall 100 und verwendet dann ein Array der ersten beiden Buchstaben der Zahlen 0 bis 11, um die Semantik der Eingabe zu bestimmen und den Wert entsprechend dem Suffix ("-ty" und "-teen"; " lv "in 12 ist ein weiterer Eckfall). Teilen Sie die Eingabe zunächst in eine Liste von Wörtern auf, ordnen Sie sie dann einem Wert zu und addieren Sie sie.

Im pythonischen Pseudocode:

                           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

Testsuite


Python 3, 218 Bytes

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

Grundsätzlich identisch mit der Pyth-Antwort.


Off-Topic:

Ich habe gerade eine sinnvolle Version der Antwort auf das Leben, das Universum und alles entdeckt: Es sind tee-durstige Zweige. Wow, Zweige, die sich nach Tee sehnen! Ich bin nicht sicher, wie viele andere Antworten dies tun, aber für meine Antwort, wenn die Eingabe "Tee-Durst-Zweige" ist, ist die Ausgabe 42.


Ich glaube, Sie können sieben Bytes sparen, indem Sie eine gepackte Zeichenfolge verwenden . Kopieren Sie die Ausgabe und setzen Sie sie "ontwthfofisiseeiniteel"in dieses Programm ein.
ETHproductions

@ETHproductions Wow, danke! Als ich das letzte Mal nachgesehen habe, war immer noch "ze" am Anfang der Saite und das Packen funktionierte nicht. Ich habe nicht noch einmal nachgesehen, nachdem ich es ausprobiert hatte. Nochmals
vielen

@ETHproductions Ja, ich habe es tatsächlich getan, es steht unter dem Pseudocode.
Busukxuan

2

Python 3, 365 361 310 303 Zeichen

Golf gespielt

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

Ungolfed

 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 Zeichen kürzer: 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(",")Aber wie ich sehe, sollte es funktionieren, ohne es der Variablen n zuzuweisen, rufe .index()es einfach direkt auf.
Manatwork

7 Zeichen kürzer: "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

Die StackExchange-Site-Engine hat eine irritierende Angewohnheit: Sie fügt unsichtbare Zeichen (U200C Zero Width Non-Joiner und U200B Zero Width Space) in den in Kommentaren angegebenen Code ein. Sie haben sie auch kopiert und eingefügt. Ich habe Ihren Beitrag bearbeitet, um sie zu entfernen.
Manatwork

2

Haskell, 252 231 Bytes

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

Dadurch wird eine Liste aller englischen Nummernnamen von "Eins" bis "Neunundneunzig" erstellt und anschließend der Index der Eingabe nachgeschlagen. Wenn es nicht existiert, sind wir im Edge-Fall "einhundert", es wird also zurückgegeben 100, andernfalls wird der Index zurückgegeben.

Ungolfed

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

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

Es erstellt einfach eine Liste mit jeder Zahl und findet den Index.


1

Japt, 82 Bytes

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

Jeder ¿ stellt ein nicht druckbares Zeichen dar. Online testen!

Basierend auf meiner Antwort von JS. Subtrahieren Sie ein Byte, wenn es sich bei der Ausgabe nicht um eine Ganzzahl handeln muss, da dies genauso aussieht wie eine Zeichenfolge.

Wie es funktioniert

+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 Bytes

Wie immer: Es stellt sich heraus, dass dies zu lang ist, um daran teilzunehmen, aber jetzt, wo ich fertig bin, wäre es eine Verschwendung, dies nicht zu posten.

Vielleicht gibt es einen offensichtlichen Weg, um weiter zu golfen, den ich übersehen habe?

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 für Testfälle


1
Wie wäre es mit einem Wechsel fzu 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:''))? Ein einzelnes String-Argument kann auch an eine Funktion wie die folgende übergeben werden:s.indexOf`lv`
ETHproductions

@ETHproductions Das ist großartig, danke! Ich wusste nicht, dass JS einen Kommaoperator hat, und die Abkürzung für String-Übergabe ist auch sehr nützlich.
Vvye

1

Perl, 158 Bytes

@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

Läuft von der Kommandozeile aus. one hundredmuss eingegeben werden "one hundred", um zu verhindern, dass es als zwei Eingänge interpretiert wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.