Skip to main content
2 of 8
added 930 characters in body
edc65
  • 32.2k
  • 3
  • 36
  • 90

#JavaScript (ES6) 432

... still golfable

This old parser of mine sometimes comes in handy - (already used in other 2 challenges)

E=(D,x,W=[],Q=['_'],O=o=>Q.push(o),P=_=>Q.pop(),V=v=>W.push(v),U=_=>W.pop(),z={'(':8,_:1,')':2},l=0,
S=i=>{for(l=0;(t=x[i++])&&t!=')';)t=='('?(O('_'),i=S(i)):z[t]?(l=0,C(t)):(l=1,V(+t));C(t),P(P()),l=1;return i},
C=n=>{for(;z[q=P()]>=z[n];V(q=='+'?a+b:q=='-'?a-b:q=='*'?a*b:q=='/'?a/b:Math.pow(a,b)))a=U(b=U());O(q),O(n)}
)=>(x=(x+')').match(/\D|\d+/g),D.match(/\w/g).map((l,p)=>z['+-/*^'['ASDME'.search(l)]]=7-p),S(0),W.pop())

console.log(E('MDASE','3+4*5^2'))
console.log(E('EMDAS','3+6*2/4-1')) // 5
console.log(E("DAMES", "3+6*2/4-1")) //3.5
console.log(E("SAD, ME", "3+6*2/4-1")) // 6
console.log(E("ME ADS", "3+5^4/2-3*2")) // 308
console.log(E("AM EDS", "4*3-sin(0.5^2)*3+1")) // 11.01038 sin not supported
console.log(E("DAMES", "4-5-6")) // -7

Ungolfed

Evaluate=(oprec,expr)=>
{
  var tokens = expr.match(/\D|\d+/g).concat(')')
  var t,a,b,v,LastV=0
  var vstack=[]
  var ostack=['_']
  var op={ '(':8, _: 1, ')':2}
  oprec.match(/\w/g).map((l,p)=>op['+-/*^'['ASDME'.search(l)]]=7-p)
  var OPush=o=>ostack.push(o)
  var OPop=_=>ostack.pop()
  var VPush=v=>vstack.push(v)
  var VPop=v=>vstack.pop()

  var Scan=i=>
  {
    LastV=0 ;
    for (; (t=tokens[i++]) && (t != ')'); )
    {
      if (t == '(')  
      {
        // if (LastV) CalcOp('*') implicit *
        OPush('_'), i=Scan(i)
      }
      else if (op[t])
        LastV=0, CalcOp(t)
      else
      {
        // if (LastV) CalcOp('*') implicit *
        LastV = 1
        VPush(+t)
      }
    }
    CalcOp(t);
    OPop();
    OPop();
    LastV=1;
    return i;
  }
  var CalcOp=nop=>
  {
    for (; op[po = OPop()] >= op[nop];)
      b=VPop(), a=VPop(), CalcV(a,b,po);
    OPush(po), OPush(nop);
  }
  var CalcV=(a,b,o)=>
  {
//    console.log('CV',a,b,o)
    if (o=='+')
      a+=b
    if (o=='-')
      a-=b
    if (o=='*')
      a*=b
    if (o=='/')
      a/=b
    if (o=='^')
      a=Math.pow(a,b)
    VPush(a)
  }
  Scan(0)

  return vstack.pop()
}


console.log(Evaluate('MDASE','3+4*5^2'))
console.log(Evaluate('EMDAS','3+6*2/4-1')) // 5
console.log(Evaluate("DAMES", "3+6*2/4-1")) //3.5
console.log(Evaluate("SAD, ME", "3+6*2/4-1")) // 6
console.log(Evaluate("ME ADS", "3+5^4/2-3*2")) // 308
console.log(Evaluate("AM EDS", "4*3-sin(0.5^2)*3+1")) // 11.01038 sin not supported
console.log(Evaluate("DAMES", "4-5-6")) // -7

edc65
  • 32.2k
  • 3
  • 36
  • 90