Taschenrechner

14

Eine vereinfachte Version des englischen Zahlenrechners

Aufgabe

Schreiben Sie ein Programm, das eine Zeichenfolge als Eingabe verwendet und das Ergebnis des Ausdrucks ausgibt.

Regeln

Die Eingabezeichenfolge hat einen Wortlaut und keine Ziffer.

Es werden keine Klammern angezeigt.

Die Reihenfolge der Berechnung wird geteilt, multipliziert, subtrahiert und addiert.

Für die gleichen Operationen müssen die Berechnungen von links nach rechts durchgeführt werden.

Alle eingegebenen Zahlen sind ganze Zahlen von -999 bis 999 (beide inklusive)

Die Ausgabe erfolgt als Ganzzahl eines beliebigen Bereichs.

Division wird immer perfekt teilbar sein und Null wird niemals ein Nenner sein.

Die Einschränkung der Groß- / Kleinschreibung für die Eingabe ist optional. Sie müssen die Gültigkeit der Eingabe nicht überprüfen.

Zahlenformat

0 to 20 -> zero,one,two...nineteen,twenty
21 to 99 -> twenty one,twenty two.....ninety eight,ninety nine
100 to 999 -> one hundred, one hundred one, one hundred two...one hundred ten....two hundred fifty....nine hundred ninety eight,nine hundred ninety nine

Für negative Zahlen: Addiere minuszum positiven Äquivalent

Operationsformat

Addition: one plus two
Subtraction: one minus two
Multiplication: one time two #Note that for one on the left of multiplication, it is one time and not times.
                two times one hundred
Division: forty divided by two

Beispiele:

o/p <- input

20     four times five
35     twenty plus fifteen
70     fifty plus five times four
-90    minus one time ninety
25     twenty one minus minus four
45     ninety divided by two
700    one time seven hundred 
555    one hundred eleven times two plus three hundred thirty three
99     one hundred plus minus one
45     forty five plus two hundred times zero
 4     four
-3     three minus three minus three

Das ist Code-Golf, also gewinnt der kürzeste Code

Vedant Kandoi
quelle
1
Duplikat? - Ich denke, das ist nah genug, um als solches angesehen zu werden.
Kirill L.
2
Es ist in der Tat sehr nah. Aber ich denke, dieser ist besser spezifiziert und hat vernünftigere Einschränkungen.
Arnauld
1
@Arnauld Ich werde dies dann offen halten, aber wenn andere anders denken, markieren Sie es einfach als Duplikat.
Vedant Kandoi
15
Ich sage one times two. Verwendet timenormal?
Jo King
2
Ich glaube , Sie bedeuten ‚ein Mal s siebenhundert‘?
6.

Antworten:

18

JavaScript (ES6), 257 252 249 235 Byte

3 Bytes gespart dank @Shaggy

s=>eval(s.split` `.map(w=>(i='zeonwohrr44fx3n5t54nn3leel8tou7fn7n98etetwthfofisiseeinihuplmitidiby'.match(/../g).findIndex(x=>~(w+w.length+w).search(x)))>28?n+' '+'+-*/ '[n='',i-29]:(n=+n+(i<28?i<20?i:i*10-180:n*99),''),n='').join``+n)

Probieren Sie es online!

Wie?

WLichW+L+W

Zahlen

 index | word              | word + length + word         | key substring
-------+-------------------+------------------------------+---------------
    0  | "zero"            | "zero4zero"                  | "ze"
    1  | "one"             | "one3one"                    | "on"
    2  | "two"             | "two3two"                    | "wo"
    3  | "three"           | "three5three"                | "hr"
    4  | "four"            | "four4four"                  | "r4"
    5  | "five"            | "five4five"                  | "4f"
    6  | "six"             | "six3six"                    | "x3"
    7  | "seven"           | "seven5seven"                | "n5"
    8  | "eight"           | "eight5eight"                | "t5"
    9  | "nine"            | "nine4nine"                  | "4n"
   10  | "ten"             | "ten3ten"                    | "n3"
   11  | "eleven"          | "eleven6eleven"              | "le"
   12  | "twelve"          | "twelve6twelve"              | "el"
   13  | "thirteen"        | "thirteen8thirteen"          | "8t"
   14  | "fourteen"        | "fourteen8fourteen"          | "ou"
   15  | "fifteen"         | "fifteen7fifteen"            | "7f"
   16  | "sixteen"         | "sixteen7sixteen"            | "n7"
   17  | "seventeen"       | "seventeen9seventeen"        | "n9"
   18  | "eighteen"        | "eighteen8eighteen"          | "8e"
   19  | "nineteen"        | "nineteen8nineteen"          | "te"
   20  | "twenty"          | "twenty6twenty"              | "tw"
   21  | "thirty"          | "thirty6thirty"              | "th"
   22  | "forty"           | "forty5forty"                | "fo"
   23  | "fifty"           | "fifty5fifty"                | "fi"
   24  | "sixty"           | "sixty5sixty"                | "si"
   25  | "seventy"         | "seventy7seventy"            | "se"
   26  | "eighty"          | "eighty6eighty"              | "ei"
   27  | "ninety"          | "ninety6ninety"              | "ni"
   28  | "hundred"         | "hundred7hundred"            | "hu"

Betreiber

 index | word              | word + length + word         | key substring
-------+-------------------+------------------------------+---------------
   29  | "plus"            | "plus4plus"                  | "pl"
   30  | "minus"           | "minus5minus"                | "mi"
   31  | "times" or "time" | "times5times" or "time4time" | "ti"
   32  | "divided"         | "divided7divided"            | "di"
   33  | "by"              | "by2by"                      | "by"

Deutung

nich

i > 28 ?                  // if the word is an operator:
  n +                     //   append n (which is either an empty string or a number)
  ' ' +                   //   append a space
  '+-*/ '[n = '', i - 29] //   reset n to an empty string and append the operator
                          //   the useless keyword 'by' is translated into a harmless space
: (                       // else:
    n =                   //   update n:
      +n + (              //     force the coercion of the current value of n to a number
        i < 28 ?          //     if the word is not 'hundred':
          i < 20 ?        //       if the value of the word is less than 'twenty':
            i             //         add i
          :               //       else:
            i * 10 - 180  //         add i * 10 - 180 (e.g. 'fifty' -> 23 * 10 - 180 = 50)
        :                 //     else:
          n * 99          //       multiply n by 100 by adding 99 * n to itself
      ),                  //
    ''                    //   remove this word from the original string
  )                       //
Arnauld
quelle
11

Perl 6 , 170 139 129 128 124 122 Bytes

-13 bytes dank nwellnhof!

{S:g/(<:N>+)+%\s/({'+'X$0})/.EVAL}o{S:g/" ҈"/00/}o{TR"⁢ʼn؊⟠"*/൰ "}o*.words>>.&{chr first *.uniname.comb(.uc),1..*}

Probieren Sie es online!

univalwieder zur Rettung! Dies schlägt (derzeit) sogar Golfsprachen wie 05AB1E!

Erläuterung:

*.words     # Split by word boundaries (in this case spaces)
       >>.{                            }  # Map each word to
           chr first             ,1..*    # The first character where:
                     *.uniname      # The unicode name of that character
                                    # e.g. DIGIT FIVE
                      .comb(.uc)    # Contains the uppercase of the word
{             }o  # Pass this list to another function
                  # That converts the list to a string
 TR"⁢ʼn؊⟠"*/൰ "    #"# And parse out the garbage characters that were wrong
                  # INVISIBLE TIMES => "*"
                  # LOZENGE DIVIDED BY HORIZONTAL RULE => "/"
                  # ARABIC-INDIC PER TEN THOUSAND SIGN => "൰" (value ten)
                  # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE => " "
{S:g/" ҈"/00/}o   # Replace the character for "hundred" with 00

{                                }o   # And finally combine with
 S:g/(<:N>+)+%\s/   # Substitute each number-like character separated by spaces
                /({'+'X$0})/   # With the numbers prefixed by '+'s, in brackets
               # This works because Perl 6 supports numeric unicode literals, like
               # ፳ => 20, ፴ => 30, ፺ => 90, etc.
                            .EVAL   # And finally evaluate the whole expression
Scherzen
quelle
7

Python 2 , 333 ... 284 277 275 Bytes

lambda s:eval(''.join((list('+-/*')+[`N(w,0)*100+N(w,2)`])['pmdt'.find(w)]for w in re.split(' *(?:(p|m)|(t|d)i|by).*? ',s)if w))
N=lambda x,y:sum(10*(w[-3:]in'lveen')+'zeontwthfofisiseeiniteel'.find(w[:2])/2*10**('y'in w)for w in x.rpartition('hundred')[y].split())
import re

Probieren Sie es online!

TFeld
quelle
5

Wolfram Language 95 94 82 Bytes

Interpreter["SemanticExpression"][#~StringReplace~{"me "->"mes ","plus m"->"m"}]&

# repräsentiert den Eingang für die reine Funktion.

Falls erforderlich, StringReplaceersetzt die "Zeit" mit Zeit " "plus minus" mit "Minus"(durch "me "->"mes ", "plus m"->"m" bezeichnet). Die von vorgeschlagenen verkürzten Ersetzungsformulare haben lirtosiast12 Byte gespart.

Interpreter["SemanticExpression"] erledigt den ganzen Rest.

DavidC
quelle
Kannst du "time "->"times "zu "me"->"mes"und "plus minus"->"minus"zu wechseln "plus m"->"m"?
Lirtosiast
Ja. Hervorragende Vorschläge.
DavidC
3

05AB1E , 166 147 141 139 135 Bytes

„byK“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“#vyN:}'tK'…§¦'+T«:'°¡„ *т«©:.•1×j›o!ĆÖ•3ôŽ9oS:'y®¨:©“‰´Øè„Æ€ººß“'tK#UX¡εð¡õK2ôJ.EO}®áX"+-**/"S:Sðì.ιJ.E

Viel zu lange. Ich werde versuchen, von hier aus Golf zu spielen.

-4 Bytes dank @Emigna .
-2 Bytes dank @JoKing .

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

byK                 # Remove "by" from the (implicit) input-string
“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“
                     # Push string "zero one two three four five six seven eight nine ten eleven twelve"
 #                   # Split by spaces
  v   }              # Loop over each of these items:
   yN:               #  Replace the item with its 0-indexed index
'tK                 '# Remove all "t"
'…§¦                '# Push string "teen", and remove the first character: "een"
    '+              '# Push string "+"
      T«             # Append 10: "+10"
        :            # Replace all "een" with "+10"
'°¡                 '# Push string "hundred"
    *               # Push string " *"
      т«             # Append 100: " *100"
        ©            # Store it in the register (without popping)
         :           # Replace all "hundred" with " *100"
.•4º»Ÿć'Rþн•        '# Push string "wenhirforfif"
            3ô       # Split the string into parts of size 3: ["wen","hir","for","fif"]
              Ž9o    # Push integer 2345
                 S   # Split to digits: [2,3,4,5]
                  :  # Replace each
'y                  '# Push string "y"
  ®                  # Push the " *100" from the register
   ¨                 # Remove the last character: " *10"
    :                # Replace all "y" with " *10"
©                    # Save the current string in the register (without popping)
 “‰´Øè„Æ€ººß“        # Push string "plus minus times time divided"
             'tK    '# Remove all "t": "plus minus imes ime divided"
                #    # Split by spaces: ["plus","minus","imes","ime","divided"]
                 U   # Pop and save it in variable `X`
                  X  # And push variable `X` back again
                   ¡ # Split the string by those operator-strings
ε          }         # Map each substring to:
 ð¡                  #  Split by spaces (NOTE: cannot be `#`; if the string contains no
                     #   spaces, `#` remains string, whereas `ð¡` wraps it in a list)
   õK                #  Remove empty strings from the list
     2ô              #  Split the list into parts of two
       J             #  Join each pair together
        .E           #  Evaluate each as a Python `eval` expression
          O          #  Sum them
®                    # Put the string from the register to the stack again
 á                   # Remove everything except for letters
  X                  # Push variable `X`: ["plus","minus","imes","ime","divided"]
   "+-**/"           # Push string "+-**/"
          S          # Split to characters: ["+","-","*","*","/"]
           :         # Replace each
S                    # Split the string of operators to loose characters
 ðì                  # Prepend a space before each
                   # Interweave all sums with these operator-characters
     J               # Join everything together to a single string
.E                   # Evaluate each as a Python `eval` expression (and output implicitly)

Sehen Sie sich meinen Tipp 05AB1E an (Abschnitte Verwendung des Wörterbuchs , Komprimieren von Zeichenfolgen, die nicht Teil des Wörterbuchs sind , und Komprimieren großer Ganzzahlen ), um zu verstehen, wie“¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“ , '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, und “‰´Øè„Æ€ººß“Arbeit.

Schritt für Schritt Beispiel:

  • Eingang: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten
  • Schritt 1: Entfernen Sie "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten
  • Schritt 2: Konvertieren Sie "Null" durch "Zwölf" mit der richtigen Zahl: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10
  • Schritt 3: Entfernen Sie alle "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10
  • Schritt 4: Ersetzen Sie alle "een" durch "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10
  • Schritt 5: Ersetzen Sie alle "hundert" durch "* 100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10
  • Schritt 6: Ersetzen Sie alle ["wen", "hir", "for", "fif"] durch die richtige Ziffer: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10
  • Schritt 7: Ersetzen Sie alle "y" durch "* 10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10
  • Schritt 8: Teilen durch ["plus", "minus", "ime", "imes", "geteilt"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]
  • Schritt 9: Teilen Sie jeweils auf Leerzeichen: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]
  • Schritt 10: Leere Gegenstände entfernen: [["2","*100","2","*10","2"],["2"],[],["5","*10","7"],["3","*100","8+10"],[],["10"]]
  • Schritt 11: In Teile der Größe 2 teilen und verbinden: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]
  • Schritt 12: Python eval jeweils:[[200,20,2],[2],"",[50,7],[300,18],"",[10]]
  • Schritt 13: Summieren Sie jeweils: [222,2,"",57,318,"",10]
  • Schritt 14: Drücken Sie die Zeichenfolge erneut aus dem Register und entfernen Sie alles außer Buchstaben: dividedimesminusplusminusminus
  • Schritt 15: Ersetzen Sie "plus", "minus", "imes", "ime", "geteilt" durch die Operatorzeichen und stellen Sie ihnen ein Leerzeichen voran: [" /"," *"," -"," +"," -"," -"]
  • Schritt 16: Verweben und verbinden Sie beide: 222 /2 * -57 +318 - -10
  • Ausgabe: Python evalden String, und implizit ausgeben:-5999.0
Kevin Cruijssen
quelle
Ich habe noch nicht versucht, eine Lösung von Grund auf zu finden, und habe mich auch nicht eingehend mit Ihrer befasst, aber ich habe einen Golf bemerkt .
Emigna
@Emigna Danke!
Kevin Cruijssen
2

sfk , 572 449 423 bytes

Dies könnte alles eine Zeile sein, aber zum Lesen habe ich Zeilenumbrüche anstelle von Leerzeichen verwendet.

xed -i
_plus_+_
_minus_-_
_times[ortext]time_*_
_divided?by_/_
+xed
"_[white][2 chars of a-z][chars of a-z]ty_[parts 1,2]0_"
"_[white][2 chars of a-z][chars of a-z]een_[part1]1[part2]_"
_ten_10_
_lev_11_
_twe_12_
+xed
_ze_0_
_on_1_
_tw_2_
_th_3_
_fo_4_
_fi_5_
_si_6_
_se_7_
_ei_8_
_ni_9_
+xed
_0[white][keep][digit]__
"_[chars of e-z ]__"
+xed
"_?dd[keep][2 digits]_[part1]_"
_?dd[keep][digit]_[part1]0_
_dd_00_
+calc #text

Probieren Sie es online!

Οurous
quelle