Worded Calculator











up vote
12
down vote

favorite
4












A simplistic version of English numeral calculator



Task



Write a program that takes a string as input and outputs the result of the expression.



Rules



The input string will be worded and not numeral.



There will be no parentheses.



Order of calculation will be divide,multiply,subtract then add.



For same operations, the calculations must be done from left to right.



All input numbers will be integers from -999 to 999 (both inclusive)



Output will be an integer of any range.



Division will always be perfectly divisible and zero will never be a denominator.



Restriction of case for input is optional. You don't have to check for the validity of the input.



Number Format



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


For negative numbers: Add minus to its positive equivalent



Operation Format



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


Examples:



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


This is code-golf so shortest code wins










share|improve this question




















  • 1




    Duplicate? - I think that's close enough to be considered as such.
    – Kirill L.
    Nov 6 at 8:45








  • 2




    It's very close indeed. But I think this one is better specified and has more reasonable limitations.
    – Arnauld
    Nov 6 at 8:53






  • 1




    @Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
    – Vedant Kandoi
    Nov 6 at 8:56






  • 14




    I say one times two. Is using time normal?
    – Jo King
    Nov 6 at 9:46








  • 2




    I think you meant 'one times seven hundred'?
    – ouflak
    Nov 6 at 17:16















up vote
12
down vote

favorite
4












A simplistic version of English numeral calculator



Task



Write a program that takes a string as input and outputs the result of the expression.



Rules



The input string will be worded and not numeral.



There will be no parentheses.



Order of calculation will be divide,multiply,subtract then add.



For same operations, the calculations must be done from left to right.



All input numbers will be integers from -999 to 999 (both inclusive)



Output will be an integer of any range.



Division will always be perfectly divisible and zero will never be a denominator.



Restriction of case for input is optional. You don't have to check for the validity of the input.



Number Format



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


For negative numbers: Add minus to its positive equivalent



Operation Format



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


Examples:



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


This is code-golf so shortest code wins










share|improve this question




















  • 1




    Duplicate? - I think that's close enough to be considered as such.
    – Kirill L.
    Nov 6 at 8:45








  • 2




    It's very close indeed. But I think this one is better specified and has more reasonable limitations.
    – Arnauld
    Nov 6 at 8:53






  • 1




    @Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
    – Vedant Kandoi
    Nov 6 at 8:56






  • 14




    I say one times two. Is using time normal?
    – Jo King
    Nov 6 at 9:46








  • 2




    I think you meant 'one times seven hundred'?
    – ouflak
    Nov 6 at 17:16













up vote
12
down vote

favorite
4









up vote
12
down vote

favorite
4






4





A simplistic version of English numeral calculator



Task



Write a program that takes a string as input and outputs the result of the expression.



Rules



The input string will be worded and not numeral.



There will be no parentheses.



Order of calculation will be divide,multiply,subtract then add.



For same operations, the calculations must be done from left to right.



All input numbers will be integers from -999 to 999 (both inclusive)



Output will be an integer of any range.



Division will always be perfectly divisible and zero will never be a denominator.



Restriction of case for input is optional. You don't have to check for the validity of the input.



Number Format



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


For negative numbers: Add minus to its positive equivalent



Operation Format



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


Examples:



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


This is code-golf so shortest code wins










share|improve this question















A simplistic version of English numeral calculator



Task



Write a program that takes a string as input and outputs the result of the expression.



Rules



The input string will be worded and not numeral.



There will be no parentheses.



Order of calculation will be divide,multiply,subtract then add.



For same operations, the calculations must be done from left to right.



All input numbers will be integers from -999 to 999 (both inclusive)



Output will be an integer of any range.



Division will always be perfectly divisible and zero will never be a denominator.



Restriction of case for input is optional. You don't have to check for the validity of the input.



Number Format



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


For negative numbers: Add minus to its positive equivalent



Operation Format



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


Examples:



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


This is code-golf so shortest code wins







code-golf






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 9 at 5:10

























asked Nov 6 at 8:14









Vedant Kandoi

46212




46212








  • 1




    Duplicate? - I think that's close enough to be considered as such.
    – Kirill L.
    Nov 6 at 8:45








  • 2




    It's very close indeed. But I think this one is better specified and has more reasonable limitations.
    – Arnauld
    Nov 6 at 8:53






  • 1




    @Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
    – Vedant Kandoi
    Nov 6 at 8:56






  • 14




    I say one times two. Is using time normal?
    – Jo King
    Nov 6 at 9:46








  • 2




    I think you meant 'one times seven hundred'?
    – ouflak
    Nov 6 at 17:16














  • 1




    Duplicate? - I think that's close enough to be considered as such.
    – Kirill L.
    Nov 6 at 8:45








  • 2




    It's very close indeed. But I think this one is better specified and has more reasonable limitations.
    – Arnauld
    Nov 6 at 8:53






  • 1




    @Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
    – Vedant Kandoi
    Nov 6 at 8:56






  • 14




    I say one times two. Is using time normal?
    – Jo King
    Nov 6 at 9:46








  • 2




    I think you meant 'one times seven hundred'?
    – ouflak
    Nov 6 at 17:16








1




1




Duplicate? - I think that's close enough to be considered as such.
– Kirill L.
Nov 6 at 8:45






Duplicate? - I think that's close enough to be considered as such.
– Kirill L.
Nov 6 at 8:45






2




2




It's very close indeed. But I think this one is better specified and has more reasonable limitations.
– Arnauld
Nov 6 at 8:53




It's very close indeed. But I think this one is better specified and has more reasonable limitations.
– Arnauld
Nov 6 at 8:53




1




1




@Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
– Vedant Kandoi
Nov 6 at 8:56




@Arnauld I will keep this open then but if others think differently, just mark it as duplicate.
– Vedant Kandoi
Nov 6 at 8:56




14




14




I say one times two. Is using time normal?
– Jo King
Nov 6 at 9:46






I say one times two. Is using time normal?
– Jo King
Nov 6 at 9:46






2




2




I think you meant 'one times seven hundred'?
– ouflak
Nov 6 at 17:16




I think you meant 'one times seven hundred'?
– ouflak
Nov 6 at 17:16










6 Answers
6






active

oldest

votes

















up vote
18
down vote













JavaScript (ES6), 257 252 249 235 bytes



Saved 3 bytes thanks to @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)


Try it online!



How?



Once the input string has been split into words, each word $W$ of length $L$ is converted to an index $i$ by looking for the first 2-character key substring that can be found in $W+L+W$.



Numbers



 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"


Operators



 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"


Interpretation



The current number is stored in $n$, which is initialized to an empty string. Given the index $i$ of the next word, the following logic applies:



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
) //





share|improve this answer






























    up vote
    10
    down vote














    Perl 6, 170 139 129 128 124 122 bytes



    -13 bytes thanks to nwellnhof!





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


    Try it online!



    unival to the rescue again! This is (currently) even beating golfing languages like 05AB1E!



    Explanation:



    *.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





    share|improve this answer






























      up vote
      7
      down vote














      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


      Try it online!






      share|improve this answer






























        up vote
        5
        down vote













        Wolfram Language 95 94 82 bytes



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


        # represents the input for the pure function.



        If necessary,StringReplace replaces "time " with times ", "plus minus" with "minus" (through "me "->"mes ","plus m"->"m", respectively). The shortened replacement forms, suggested by lirtosiast, saved 12 bytes.



        Interpreter["SemanticExpression"] does all the rest.






        share|improve this answer























        • Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
          – lirtosiast
          10 hours ago












        • Yes. Excellent suggestions.
          – DavidC
          8 hours ago


















        up vote
        3
        down vote














        05AB1E, 166 147 141 139 bytes



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


        Way too long.. Will try to golf it down from here.



        -4 byte thanks to @Emigna.

        -2 bytes thanks to @JoKing.



        Try it online or verify all test cases.



        Explanation:





        „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
        .ι # Interweave all sums with these operator-characters
        J # Join everything together to a single string
        „-- # Push string "--"
        '+ '# Push string "+"
        : # Replace all "--" with "+"
        .E # Evaluate each as a Python `eval` expression (and output implicitly)


        See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand how “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, and “‰´Øè„Æ€ººß“ work.



        Step by step example:





        • Input: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten

        • Step 1: Remove "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten

        • Step 2: Convert "zero" through "twelve" with the correct number: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10

        • Step 3: Remove all "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10

        • Step 4: Replace all "een" with "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10

        • Step 5: Replace all "hundred" with " *100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10

        • Step 6: Replace all ["wen","hir","for","fif"] with the correct digit: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10

        • Step 7: Replace all "y" with " *10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10

        • Step 8: Split by ["plus","minus","ime","imes","divided"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]

        • Step 9: Split each on spaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]

        • Step 10: Remove empty items: [["2","*100","2","*10","2"],["2"],,["5","*10","7"],["3","*100","8+10"],,["10"]]

        • Step 11: Split into parts of size 2 and join: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]

        • Step 12: Python eval each: [[200,20,2],[2],"",[50,7],[300,18],"",[10]]

        • Step 13: Sum each: [222,2,"",57,318,"",10]

        • Step 14: Re-push the string from the register, and remove everything except letters: dividedimesminusplusminusminus

        • Step 15: Replace "plus","minus","imes","ime","divided" with the operator characters: ["/","*","-","+","-","-"]

        • Step 16: Interweave and join both together: 222/2*-57+318--10

        • Step 17: Replace any "--" with "+": 222/2*-57+318+10


        • Output: Python eval the string, and output implicitly: -5999.0






        share|improve this answer























        • Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
          – Emigna
          Nov 6 at 12:33










        • @Emigna Thanks!
          – Kevin Cruijssen
          Nov 6 at 13:08


















        up vote
        2
        down vote














        sfk, 572 449 423 bytes



        This could all be one line, but for the purposes of reading it I used newlines instead of spaces.



        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


        Try it online!






        share|improve this answer























          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "200"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f175369%2fworded-calculator%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          6 Answers
          6






          active

          oldest

          votes








          6 Answers
          6






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          18
          down vote













          JavaScript (ES6), 257 252 249 235 bytes



          Saved 3 bytes thanks to @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)


          Try it online!



          How?



          Once the input string has been split into words, each word $W$ of length $L$ is converted to an index $i$ by looking for the first 2-character key substring that can be found in $W+L+W$.



          Numbers



           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"


          Operators



           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"


          Interpretation



          The current number is stored in $n$, which is initialized to an empty string. Given the index $i$ of the next word, the following logic applies:



          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
          ) //





          share|improve this answer



























            up vote
            18
            down vote













            JavaScript (ES6), 257 252 249 235 bytes



            Saved 3 bytes thanks to @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)


            Try it online!



            How?



            Once the input string has been split into words, each word $W$ of length $L$ is converted to an index $i$ by looking for the first 2-character key substring that can be found in $W+L+W$.



            Numbers



             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"


            Operators



             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"


            Interpretation



            The current number is stored in $n$, which is initialized to an empty string. Given the index $i$ of the next word, the following logic applies:



            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
            ) //





            share|improve this answer

























              up vote
              18
              down vote










              up vote
              18
              down vote









              JavaScript (ES6), 257 252 249 235 bytes



              Saved 3 bytes thanks to @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)


              Try it online!



              How?



              Once the input string has been split into words, each word $W$ of length $L$ is converted to an index $i$ by looking for the first 2-character key substring that can be found in $W+L+W$.



              Numbers



               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"


              Operators



               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"


              Interpretation



              The current number is stored in $n$, which is initialized to an empty string. Given the index $i$ of the next word, the following logic applies:



              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
              ) //





              share|improve this answer














              JavaScript (ES6), 257 252 249 235 bytes



              Saved 3 bytes thanks to @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)


              Try it online!



              How?



              Once the input string has been split into words, each word $W$ of length $L$ is converted to an index $i$ by looking for the first 2-character key substring that can be found in $W+L+W$.



              Numbers



               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"


              Operators



               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"


              Interpretation



              The current number is stored in $n$, which is initialized to an empty string. Given the index $i$ of the next word, the following logic applies:



              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
              ) //






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 6 at 13:57

























              answered Nov 6 at 10:05









              Arnauld

              68.6k584289




              68.6k584289






















                  up vote
                  10
                  down vote














                  Perl 6, 170 139 129 128 124 122 bytes



                  -13 bytes thanks to nwellnhof!





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


                  Try it online!



                  unival to the rescue again! This is (currently) even beating golfing languages like 05AB1E!



                  Explanation:



                  *.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





                  share|improve this answer



























                    up vote
                    10
                    down vote














                    Perl 6, 170 139 129 128 124 122 bytes



                    -13 bytes thanks to nwellnhof!





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


                    Try it online!



                    unival to the rescue again! This is (currently) even beating golfing languages like 05AB1E!



                    Explanation:



                    *.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





                    share|improve this answer

























                      up vote
                      10
                      down vote










                      up vote
                      10
                      down vote










                      Perl 6, 170 139 129 128 124 122 bytes



                      -13 bytes thanks to nwellnhof!





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


                      Try it online!



                      unival to the rescue again! This is (currently) even beating golfing languages like 05AB1E!



                      Explanation:



                      *.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





                      share|improve this answer















                      Perl 6, 170 139 129 128 124 122 bytes



                      -13 bytes thanks to nwellnhof!





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


                      Try it online!



                      unival to the rescue again! This is (currently) even beating golfing languages like 05AB1E!



                      Explanation:



                      *.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






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited 17 mins ago

























                      answered Nov 6 at 11:21









                      Jo King

                      19k242102




                      19k242102






















                          up vote
                          7
                          down vote














                          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


                          Try it online!






                          share|improve this answer



























                            up vote
                            7
                            down vote














                            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


                            Try it online!






                            share|improve this answer

























                              up vote
                              7
                              down vote










                              up vote
                              7
                              down vote










                              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


                              Try it online!






                              share|improve this answer















                              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


                              Try it online!







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Nov 6 at 12:36

























                              answered Nov 6 at 9:10









                              TFeld

                              13.5k21139




                              13.5k21139






















                                  up vote
                                  5
                                  down vote













                                  Wolfram Language 95 94 82 bytes



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


                                  # represents the input for the pure function.



                                  If necessary,StringReplace replaces "time " with times ", "plus minus" with "minus" (through "me "->"mes ","plus m"->"m", respectively). The shortened replacement forms, suggested by lirtosiast, saved 12 bytes.



                                  Interpreter["SemanticExpression"] does all the rest.






                                  share|improve this answer























                                  • Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                    – lirtosiast
                                    10 hours ago












                                  • Yes. Excellent suggestions.
                                    – DavidC
                                    8 hours ago















                                  up vote
                                  5
                                  down vote













                                  Wolfram Language 95 94 82 bytes



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


                                  # represents the input for the pure function.



                                  If necessary,StringReplace replaces "time " with times ", "plus minus" with "minus" (through "me "->"mes ","plus m"->"m", respectively). The shortened replacement forms, suggested by lirtosiast, saved 12 bytes.



                                  Interpreter["SemanticExpression"] does all the rest.






                                  share|improve this answer























                                  • Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                    – lirtosiast
                                    10 hours ago












                                  • Yes. Excellent suggestions.
                                    – DavidC
                                    8 hours ago













                                  up vote
                                  5
                                  down vote










                                  up vote
                                  5
                                  down vote









                                  Wolfram Language 95 94 82 bytes



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


                                  # represents the input for the pure function.



                                  If necessary,StringReplace replaces "time " with times ", "plus minus" with "minus" (through "me "->"mes ","plus m"->"m", respectively). The shortened replacement forms, suggested by lirtosiast, saved 12 bytes.



                                  Interpreter["SemanticExpression"] does all the rest.






                                  share|improve this answer














                                  Wolfram Language 95 94 82 bytes



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


                                  # represents the input for the pure function.



                                  If necessary,StringReplace replaces "time " with times ", "plus minus" with "minus" (through "me "->"mes ","plus m"->"m", respectively). The shortened replacement forms, suggested by lirtosiast, saved 12 bytes.



                                  Interpreter["SemanticExpression"] does all the rest.







                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited 8 hours ago

























                                  answered Nov 6 at 15:13









                                  DavidC

                                  23.5k243100




                                  23.5k243100












                                  • Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                    – lirtosiast
                                    10 hours ago












                                  • Yes. Excellent suggestions.
                                    – DavidC
                                    8 hours ago


















                                  • Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                    – lirtosiast
                                    10 hours ago












                                  • Yes. Excellent suggestions.
                                    – DavidC
                                    8 hours ago
















                                  Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                  – lirtosiast
                                  10 hours ago






                                  Can you change "time "->"times " to "me"->"mes" and "plus minus"->"minus" to "plus m"->"m"?
                                  – lirtosiast
                                  10 hours ago














                                  Yes. Excellent suggestions.
                                  – DavidC
                                  8 hours ago




                                  Yes. Excellent suggestions.
                                  – DavidC
                                  8 hours ago










                                  up vote
                                  3
                                  down vote














                                  05AB1E, 166 147 141 139 bytes



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


                                  Way too long.. Will try to golf it down from here.



                                  -4 byte thanks to @Emigna.

                                  -2 bytes thanks to @JoKing.



                                  Try it online or verify all test cases.



                                  Explanation:





                                  „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
                                  .ι # Interweave all sums with these operator-characters
                                  J # Join everything together to a single string
                                  „-- # Push string "--"
                                  '+ '# Push string "+"
                                  : # Replace all "--" with "+"
                                  .E # Evaluate each as a Python `eval` expression (and output implicitly)


                                  See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand how “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, and “‰´Øè„Æ€ººß“ work.



                                  Step by step example:





                                  • Input: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 1: Remove "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 2: Convert "zero" through "twelve" with the correct number: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10

                                  • Step 3: Remove all "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10

                                  • Step 4: Replace all "een" with "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10

                                  • Step 5: Replace all "hundred" with " *100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10

                                  • Step 6: Replace all ["wen","hir","for","fif"] with the correct digit: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10

                                  • Step 7: Replace all "y" with " *10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10

                                  • Step 8: Split by ["plus","minus","ime","imes","divided"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]

                                  • Step 9: Split each on spaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]

                                  • Step 10: Remove empty items: [["2","*100","2","*10","2"],["2"],,["5","*10","7"],["3","*100","8+10"],,["10"]]

                                  • Step 11: Split into parts of size 2 and join: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]

                                  • Step 12: Python eval each: [[200,20,2],[2],"",[50,7],[300,18],"",[10]]

                                  • Step 13: Sum each: [222,2,"",57,318,"",10]

                                  • Step 14: Re-push the string from the register, and remove everything except letters: dividedimesminusplusminusminus

                                  • Step 15: Replace "plus","minus","imes","ime","divided" with the operator characters: ["/","*","-","+","-","-"]

                                  • Step 16: Interweave and join both together: 222/2*-57+318--10

                                  • Step 17: Replace any "--" with "+": 222/2*-57+318+10


                                  • Output: Python eval the string, and output implicitly: -5999.0






                                  share|improve this answer























                                  • Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                    – Emigna
                                    Nov 6 at 12:33










                                  • @Emigna Thanks!
                                    – Kevin Cruijssen
                                    Nov 6 at 13:08















                                  up vote
                                  3
                                  down vote














                                  05AB1E, 166 147 141 139 bytes



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


                                  Way too long.. Will try to golf it down from here.



                                  -4 byte thanks to @Emigna.

                                  -2 bytes thanks to @JoKing.



                                  Try it online or verify all test cases.



                                  Explanation:





                                  „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
                                  .ι # Interweave all sums with these operator-characters
                                  J # Join everything together to a single string
                                  „-- # Push string "--"
                                  '+ '# Push string "+"
                                  : # Replace all "--" with "+"
                                  .E # Evaluate each as a Python `eval` expression (and output implicitly)


                                  See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand how “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, and “‰´Øè„Æ€ººß“ work.



                                  Step by step example:





                                  • Input: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 1: Remove "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 2: Convert "zero" through "twelve" with the correct number: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10

                                  • Step 3: Remove all "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10

                                  • Step 4: Replace all "een" with "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10

                                  • Step 5: Replace all "hundred" with " *100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10

                                  • Step 6: Replace all ["wen","hir","for","fif"] with the correct digit: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10

                                  • Step 7: Replace all "y" with " *10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10

                                  • Step 8: Split by ["plus","minus","ime","imes","divided"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]

                                  • Step 9: Split each on spaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]

                                  • Step 10: Remove empty items: [["2","*100","2","*10","2"],["2"],,["5","*10","7"],["3","*100","8+10"],,["10"]]

                                  • Step 11: Split into parts of size 2 and join: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]

                                  • Step 12: Python eval each: [[200,20,2],[2],"",[50,7],[300,18],"",[10]]

                                  • Step 13: Sum each: [222,2,"",57,318,"",10]

                                  • Step 14: Re-push the string from the register, and remove everything except letters: dividedimesminusplusminusminus

                                  • Step 15: Replace "plus","minus","imes","ime","divided" with the operator characters: ["/","*","-","+","-","-"]

                                  • Step 16: Interweave and join both together: 222/2*-57+318--10

                                  • Step 17: Replace any "--" with "+": 222/2*-57+318+10


                                  • Output: Python eval the string, and output implicitly: -5999.0






                                  share|improve this answer























                                  • Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                    – Emigna
                                    Nov 6 at 12:33










                                  • @Emigna Thanks!
                                    – Kevin Cruijssen
                                    Nov 6 at 13:08













                                  up vote
                                  3
                                  down vote










                                  up vote
                                  3
                                  down vote










                                  05AB1E, 166 147 141 139 bytes



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


                                  Way too long.. Will try to golf it down from here.



                                  -4 byte thanks to @Emigna.

                                  -2 bytes thanks to @JoKing.



                                  Try it online or verify all test cases.



                                  Explanation:





                                  „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
                                  .ι # Interweave all sums with these operator-characters
                                  J # Join everything together to a single string
                                  „-- # Push string "--"
                                  '+ '# Push string "+"
                                  : # Replace all "--" with "+"
                                  .E # Evaluate each as a Python `eval` expression (and output implicitly)


                                  See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand how “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, and “‰´Øè„Æ€ººß“ work.



                                  Step by step example:





                                  • Input: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 1: Remove "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 2: Convert "zero" through "twelve" with the correct number: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10

                                  • Step 3: Remove all "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10

                                  • Step 4: Replace all "een" with "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10

                                  • Step 5: Replace all "hundred" with " *100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10

                                  • Step 6: Replace all ["wen","hir","for","fif"] with the correct digit: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10

                                  • Step 7: Replace all "y" with " *10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10

                                  • Step 8: Split by ["plus","minus","ime","imes","divided"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]

                                  • Step 9: Split each on spaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]

                                  • Step 10: Remove empty items: [["2","*100","2","*10","2"],["2"],,["5","*10","7"],["3","*100","8+10"],,["10"]]

                                  • Step 11: Split into parts of size 2 and join: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]

                                  • Step 12: Python eval each: [[200,20,2],[2],"",[50,7],[300,18],"",[10]]

                                  • Step 13: Sum each: [222,2,"",57,318,"",10]

                                  • Step 14: Re-push the string from the register, and remove everything except letters: dividedimesminusplusminusminus

                                  • Step 15: Replace "plus","minus","imes","ime","divided" with the operator characters: ["/","*","-","+","-","-"]

                                  • Step 16: Interweave and join both together: 222/2*-57+318--10

                                  • Step 17: Replace any "--" with "+": 222/2*-57+318+10


                                  • Output: Python eval the string, and output implicitly: -5999.0






                                  share|improve this answer















                                  05AB1E, 166 147 141 139 bytes



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


                                  Way too long.. Will try to golf it down from here.



                                  -4 byte thanks to @Emigna.

                                  -2 bytes thanks to @JoKing.



                                  Try it online or verify all test cases.



                                  Explanation:





                                  „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
                                  .ι # Interweave all sums with these operator-characters
                                  J # Join everything together to a single string
                                  „-- # Push string "--"
                                  '+ '# Push string "+"
                                  : # Replace all "--" with "+"
                                  .E # Evaluate each as a Python `eval` expression (and output implicitly)


                                  See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress strings not part of the dictionary?, and How to compress large integers?) to understand how “¡×€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š—¿áÓÁÏ“, '…§, '°¡, .•4º»Ÿć'Rþн•, Ž9o, and “‰´Øè„Æ€ººß“ work.



                                  Step by step example:





                                  • Input: two hundred twenty two divided by two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 1: Remove "by": two hundred twenty two divided two times minus fifty seven plus three hundred eighteen minus minus ten

                                  • Step 2: Convert "zero" through "twelve" with the correct number: 2 hundred twenty 2 divided 2 times minus fifty 7 plus 3 hundred 8een minus minus 10

                                  • Step 3: Remove all "t": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8een minus minus 10

                                  • Step 4: Replace all "een" with "+10": 2 hundred weny 2 divided 2 imes minus fify 7 plus 3 hundred 8+10 minus minus 10

                                  • Step 5: Replace all "hundred" with " *100": 2 *100 weny 2 divided 2 imes minus fify 7 plus 3 *100 8+10 minus minus 10

                                  • Step 6: Replace all ["wen","hir","for","fif"] with the correct digit: 2 *100 2y 2 divided 2 imes minus 5y 7 plus 3 *100 8+10 minus minus 10

                                  • Step 7: Replace all "y" with " *10": 2 *100 2 *10 2 divided 2 imes minus 5 *10 7 plus 3 *100 8+10 minus minus 10

                                  • Step 8: Split by ["plus","minus","ime","imes","divided"]: ["2 *100 2 *10 2 "," 2 "," "," 5 *10 7 "," 3 *100 8+10 "," "," 10"]

                                  • Step 9: Split each on spaces: [["2","","*100","2","*10","2",""],["","","2",""],["",""],["","5","*10","7",""],["","3","","*100","8+10",""],["",""],["","10"]]

                                  • Step 10: Remove empty items: [["2","*100","2","*10","2"],["2"],,["5","*10","7"],["3","*100","8+10"],,["10"]]

                                  • Step 11: Split into parts of size 2 and join: [["2*100","2*10","2"],["2"],"",["5*10","7"],["3*100","8+10"],"",["10"]]

                                  • Step 12: Python eval each: [[200,20,2],[2],"",[50,7],[300,18],"",[10]]

                                  • Step 13: Sum each: [222,2,"",57,318,"",10]

                                  • Step 14: Re-push the string from the register, and remove everything except letters: dividedimesminusplusminusminus

                                  • Step 15: Replace "plus","minus","imes","ime","divided" with the operator characters: ["/","*","-","+","-","-"]

                                  • Step 16: Interweave and join both together: 222/2*-57+318--10

                                  • Step 17: Replace any "--" with "+": 222/2*-57+318+10


                                  • Output: Python eval the string, and output implicitly: -5999.0







                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited 10 hours ago

























                                  answered Nov 6 at 11:47









                                  Kevin Cruijssen

                                  33.8k554180




                                  33.8k554180












                                  • Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                    – Emigna
                                    Nov 6 at 12:33










                                  • @Emigna Thanks!
                                    – Kevin Cruijssen
                                    Nov 6 at 13:08


















                                  • Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                    – Emigna
                                    Nov 6 at 12:33










                                  • @Emigna Thanks!
                                    – Kevin Cruijssen
                                    Nov 6 at 13:08
















                                  Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                  – Emigna
                                  Nov 6 at 12:33




                                  Haven't tried to make a solution from scratch or studied yours in detail, but I noticed one golf.
                                  – Emigna
                                  Nov 6 at 12:33












                                  @Emigna Thanks!
                                  – Kevin Cruijssen
                                  Nov 6 at 13:08




                                  @Emigna Thanks!
                                  – Kevin Cruijssen
                                  Nov 6 at 13:08










                                  up vote
                                  2
                                  down vote














                                  sfk, 572 449 423 bytes



                                  This could all be one line, but for the purposes of reading it I used newlines instead of spaces.



                                  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


                                  Try it online!






                                  share|improve this answer



























                                    up vote
                                    2
                                    down vote














                                    sfk, 572 449 423 bytes



                                    This could all be one line, but for the purposes of reading it I used newlines instead of spaces.



                                    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


                                    Try it online!






                                    share|improve this answer

























                                      up vote
                                      2
                                      down vote










                                      up vote
                                      2
                                      down vote










                                      sfk, 572 449 423 bytes



                                      This could all be one line, but for the purposes of reading it I used newlines instead of spaces.



                                      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


                                      Try it online!






                                      share|improve this answer















                                      sfk, 572 449 423 bytes



                                      This could all be one line, but for the purposes of reading it I used newlines instead of spaces.



                                      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


                                      Try it online!







                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Nov 8 at 6:26

























                                      answered Nov 8 at 1:13









                                      Οurous

                                      5,76311031




                                      5,76311031






























                                           

                                          draft saved


                                          draft discarded



















































                                           


                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f175369%2fworded-calculator%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          這個網誌中的熱門文章

                                          Tangent Lines Diagram Along Smooth Curve

                                          Yusuf al-Mu'taman ibn Hud

                                          Zucchini