7
\$\begingroup\$

Task

Given an input, evaluate it as a mathematical equation following the order of operations.

But, instead of the using PEMDAS, we drop the parentheses and exponentiation and introduce spaces - SMDAS - spaces, then multiplication & division, then addition & subtraction.

How does that work?

Every operator with more spaces around it gets more precedence - but that can change from one side to the other. Usual precedence test - 2+2*2 still gets evaluated to 6 - so does 2 + 2*2 - which would be spelled out like two .. plus .. two-times-two, but 2+2 *2 or 2+2 * 2 would equal 8 - twoPlusTwo .. times two.

So, from any operator to any side every operator and number with less spaces can be grouped as in parentheses and then calculated as normal.

Alternatively, you can think of it as spaces around operators dropping the operator lower in precedence, or if the spaces are different on each side, drop the precedence on each side differently.

Examples

input = output
2+2*2 = 6
2+2-2 = 2
2+12/6 = 4
228+456/228 = 230
2+0*42 = 2
73-37-96+200 = 140

2+2 * 2 = 8
5*6  +  7*8   -3  *5 = 415
4+4*4+ 4*4-4*2  /  4*4-2 = 2
228+456 /228 = 3
2+2 * 3-6 * 4/2 + 4*3  +  1000 / 5*5 / 5-3  +  1 = 9
2+0 * 42 = 84
5*5 *7-1 = 174

Notes

  • The input will always be valid - it will always contain at least 2 numbers, separated by a sign (-+/* (for which you may use alternatives such as or ÷))
  • The input will never end or start in spaces.
  • There will never be unary subtraction - -4*-6.
  • There will never be division by zero.
  • There may be negative integers in the process but never in the output.
  • Division is only required to work for integers.
  • Floating-point inaccuracies at any step of the process are fine.
  • This is , shortest answer per language wins!
\$\endgroup\$
4
  • \$\begingroup\$ Is a trailing .0 okay? \$\endgroup\$
    – Okx
    Commented Jul 14, 2017 at 14:50
  • \$\begingroup\$ @Okx Yeah, and even some .000001 as covered by Floating-point inaccuracies at any step of the process are fine \$\endgroup\$
    – dzaima
    Commented Jul 14, 2017 at 14:51
  • \$\begingroup\$ Could u plz add an intermediate well parenthesize expression for your list of example? \$\endgroup\$
    – mdahmoune
    Commented Jul 14, 2017 at 15:06
  • \$\begingroup\$ @mdahmoune As the challenge doesn't require to be done with parentheses, I'd say it's not required. \$\endgroup\$
    – dzaima
    Commented Jul 14, 2017 at 15:14

3 Answers 3

16
\$\begingroup\$

Japt, 15 bytes

OvUr" +%d"_rS'(

Test it online!

How it works

This challenge was practically made for Japt. I shall attempt to explain how:

Japt is basically a shortened version of JavaScript. In fact, after making some changes to the code ("transpiling" to JS), it is evaluated directly as JavaScript. What comes in handy here is that a space in Japt becomes ) in JavaScript (a feature I occasionally regret adding, as it makes it hard to write "ungolfed" Japt code), and missing parentheses are automatically added.

What this all means for this challenge is that we can obtain the correct result simply by changing all spaces after an operator (before a number) to left-parentheses:

5*6  +  7*8   -3  *5    Original string
5*6  +((7*8   -3  *5    Japt code that evaluates to the correct number

When transpiled to JS, the changes mentioned above are made, which results in this:

     5*6  +((7*8   -3  *5    Japt code
(((((5*6))+((7*8)))-3))*5    transpiled JS code

The JS code is then evaluated, which gives the expected result.

OvUr" +%d"_rS'(    Implicit: U = input string
  Ur" +%d"         Replace each match of / +\d/ in U with
          _rS'(      the match with each Space replaced with a '('.
Ov                 Evaluate the result as Japt.
                   Implicit: output result of last expression
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Wow, talk about the right language for the job. \$\endgroup\$
    – notjagan
    Commented Jul 14, 2017 at 15:25
3
\$\begingroup\$

V, 59 bytes

òÍ ¨Ä*[+*¯-]©/)±
ͨ[+*¯-]Ä*© /±(ò
Ïò])|é(kòJïò[(Á)jòHDi="

Try it online!

I'm looking into golfing this down more later. The idea is that it turns spaces on the left of an operator into ) and ( on the right, the surrounds with appropriate () to make all parens match, and calculates the line. Mostly my regexes need work:

 \(\D*[+*\/-]\)/)\1
\([+*\/-]\D*\) /\1(
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 116 bytes

f=
s=>(s=s.replace(/./g,c=>c>` `?(b=1/c?`)`:`(`,c):b),g=c=>s.split(c).length,eval(`(`.repeat(g`)`)+s+`)`.repeat(g`(`)))
<input><input type=button value=Evaluate onclick=o.textContent=``,o.textContent=f(this.previousSibling.value)><pre id=o>

Changes the spaces into the appropriate brackets, then adds matching brackets on each side (at least one pair of which will be redundant, not that it matters) and evaluates the result.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.