Dames, mach ein bisschen Mathe!

19

Die Reihenfolge der Operationen, PEMDAS, ist eine Grundregel in der Mathematik, die uns sagt, welche Ordnungsoperationen ausgeführt werden sollen:

"Klammern, Exponenten, Multiplikation und Division sowie Addition und Subtraktion"

Das Problem ist, dass PEMDAS nicht sehr vielseitig ist! Was wäre, wenn Sie es in einer anderen Reihenfolge tun wollten? Wir werden uns nicht mit den Klammern anlegen, also behalten wir sie (zuerst) dort, wo sie sind.

Erstellen Sie ein Programm mit zwei Argumenten:

  • Ein String, der angibt, in welcher Reihenfolge die Operationen ausgeführt werden sollen. Einige Beispiele sind "DAMES", "SAD, ME", "ME SAD", "MEADS". Ja, Leerzeichen und Kommas sind in Ordnung, da die Reihenfolge dadurch leichter zu merken ist.
    • Folgende Vorschläge im Chat: Die Unterstützung von Leerzeichen und Kommas ist jetzt optional.
    • Wenn einer der Buchstaben fehlt oder zusätzliche Buchstaben fehlen sollten, können Sie die Eingabe als ungültig betrachten und sie so behandeln, wie Sie möchten.
  • Eine Zeichenfolge oder ein Ausdruck, der den Ausdruck enthält, der ausgewertet werden soll.

Gibt das Ergebnis des Ausdrucks entweder als Dezimalzahl oder als Ganzzahl zurück. Wenn die Antwort keine Ganzzahl ist, muss sie als Dezimalzahl zurückgegeben werden.

Regeln:

  • Es ist in Ordnung, die beiden Eingabeargumente zu einem zu kombinieren, wenn dies in Ihrer Sprache einfacher ist.
  • Es muss keine Zeichenfolge sein, aber es muss Buchstaben haben. Sie können Addition nicht durch 1, Division durch 2 usw. ersetzen.
  • Sie können wählen, welcher Eingang zuerst ist.
  • Der Ausdruck wird von rechts nach links von links nach rechts ausgewertet . (Änderung der Regel. Alle Einsendungen von Postern in den ersten 12 Stunden, bei denen dies umgekehrt ist, werden akzeptiert.)
  • Die Operationen verwenden Sie die Symbole: ( ) ^ * / + -. Zum Beispiel können Sie nicht ¤statt +zum Hinzufügen verwenden.
  • Leerzeichen im Eingabeausdruck gelten nicht als Eingabe
  • Unary +/- ist nicht als Eingabe gültig, wenn es direkt auf + oder - folgt. Als 3+-2ungültige Eingabe betrachten. Es kann behandelt werden, wie Sie möchten (es muss kein Fehler vorliegen). Wenn +oder -anderen Operator folgt als plus oder minus, ist es die übliche Art und Weise behandelt: 3*-3 = -9,sin(-2)=-0.909
  • Das Programm muss die Buchstaben streng folgen, so "EMDAS", 1-3+4 => -6, und "EMDSA", 1-3+4 => 2.

Beispiele:

Input:   "EMDAS", "3+6*2/4-1"   // -> 3+12/4-1 -> 3+3-1 -> 6-1 -> 5
Output:  5

Input:   "DAMES", "3+6*2/4-1"   // -> 3+6*0.5-1 -> 9*0.5-1 -> 4.5-1 -> 3.5
Output:  3.5

Input:   "SAD, ME", "3+6*2/4-1"  // -> 3+6*2/3 -> 9*2/3 -> 9*0.66667 -> 6   
Output:  6

Input:   "ME ADS", "3+5^4/2-3*2 // -> 3+5^4/2-6 -> 3+625/2-6 -> 628/2-6 -> 314-6 -> 308
Output:  308

Input:   "AM EDS", "4*3-sin(0.5^2)*3+1" // -> 4*3-sin(0.5^2)*4 -> 12-sin(0.5^2)*4 -> 4*3-(4*sin(0.5^2)) -> 12-(4*sin(0.5^2)) -> 12-(4*sin(0.25)) -> 12-(4*0.24740) -> 12-0.98961 -> 11.01038
Output:  11.01038

Input:   "DAMES", "4-5-6"   // -> (4-5)-6 -> = -7  
Output:  -7                  // NOT: -> 4-(5-6) -> 4-(-1) -> 5

Beachten Sie, dass die Klammern hinzugefügt wurden, um anzuzeigen, dass die Multiplikation 4*sin(0.5^2)vor der Exponentiation ausgewertet wird.

Das ist Code Golf, also gewinnt der kürzeste Code in Bytes.

Stewie Griffin
quelle
2
Es ist überhaupt nicht genau dasselbe, aber diese Herausforderung besteht darin, zu einer anderen Reihenfolge von Operationen überzugehen, und war die Inspiration, die mich dazu veranlasste, etwas Ähnliches zu tun. Ich denke, die Haskell-Antwort könnte möglicherweise überarbeitet werden, um diese Frage zu beantworten ... Ich bin mir nicht sicher, ob es sich um ein striktes Duplikat handelt, aber ich mag die Idee, diese Herausforderung zu bestehen, ohne die native Fähigkeit, die Operatoren direkt zu ändern!
Dom Hastings
2
Bonus für Funktionen entfernt, aber es gibt immer noch sin () in den Beispielen.
Edc65
Etwas schlimmer als die oben erwähnte Herausforderung, und ich werde sie nicht als Duplikat anfechten (obwohl ein Link zum Original wünschenswert gewesen wäre). Es ist jedoch für jeden klar, dass der böse Regisseur von The 2560 nichts anderes als @Stewie Griffin ist. Ich muss sagen, ich bin nicht überrascht.
Jake
In Großbritannien wird es oft als BODMASoder BIDMASin der Schule unterrichtet. B= Klammern Ooder I= Reihenfolge oder Indizes.
BadHorsie
Wird pgebraucht Es ist nicht in den Beispielen
ev3commander

Antworten:

7

JavaScript (ES6) 349 353 387 400

... vielleicht noch golfen

Dieser alte Parser von mir ist manchmal praktisch - (bereits in anderen 2 Herausforderungen verwendet)

E=
(d,x,W=[],Q=['_'],h={'(':1,_:8,')':7},z=1,C=n=>{for(;h[q=Q.pop()]<=h[n];W.push(q=='^'?Math.pow(a,b):eval(`a${q}b`)))a=W.pop(b=W.pop());Q.push(q,n)})=>([...d].map(l=>h[l='+-/*^'['ASDME'.search(l)]]=(d+=!!l),d=1),(x+')').replace(/\D|\d+/g,t=>(u=~~h[t])-1?u-7?u?z&&t=='-'?z=-z:C(t,z=1):(W.push(z*t),z=0):Q.pop(Q.pop(C(t),z=0)):z=!!Q.push('_')),W.pop())

// TEST
console.log=(...x)=>O.innerHTML+=x.join` `+'\n'

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

// MORE READABLE
U=(d,x,W=[],Q=['_'],h={'(':1,_:8,')':7},z=1,
  C=n=>{
    for(;h[q=Q.pop()]<=h[n];
        W.push(q=='^'?Math.pow(a,b):eval(`a${q}b`)))
      a=W.pop(b=W.pop());
    Q.push(q,n)
  }
)=>(
  [...d].map(l=>h[l='+-/*^'['ASDME'.search(l)]]=(d+=!!l),d=1),
  (x+')').replace(/\D|\d+/g,t=> 
     (u=~~h[t])-1
       ?u-7
         ?u
           ?z&&t=='-'?z=-z:C(t,z=1)
           :(W.push(z*t),z=0)
         :Q.pop(Q.pop(C(t),z=0))
       :(Q.push('_'),z=1)
  ),
  W.pop()
)
<pre id=O></pre>

Ungolfed

Evaluate=(oprec,expr)=>
{
  var tokens = expr.match(/\D|\d+/g).concat(')')
  var t,a,b,v, SignV
  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=>
  {
    SignV = 1
    for (; t=tokens[i++]; )
    {
      if (t == '(')  
      {
        OPush('_')
        SignV = 1
      }
      else if (t == ')')
      {
        CalcOp(t);
        OPop();
        OPop();
        SignV = 0
      }
      else if (op[t])
      {
        if (SignV && t=='-')
          SignV = -SignV
        else
          CalcOp(t), SignV = 1
      }  
      else
      {
        VPush(SignV*t)
        SignV=0
      }
    }
  }
  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 VPop()
}

console.log=(...x)=>O.innerHTML+=x.join` `+'\n'

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
<pre id=O></pre>

edc65
quelle
Ich denke, Sie können das Leerzeichen (t=>t=='('?(z=1, Q.push('_'))zusammen mit allen Zeilenumbrüchen entfernen.
Conor O'Brien
1
@ CᴏɴᴏʀO'Bʀɪᴇɴ daran arbeiten. Thanks
edc65
Ich denke, Sie können die Math.pow(a,b)zu änderna**b
Kritixi Lithos
@KritixiLithos ja, aber es wäre nicht mehr ES6
edc65
6

R 3.3.2: 209 196 187 177 Bytes

Die Idee ist, die nicht-arithmetischen Operatoren <, &, |, ~,? wo wir den Vorrang kennen (siehe ?Syntaxin R - aber vor dem Überschreiben;)) und sie mit den gegebenen arithmetischen Operatoren überschreiben. Die Zuordnung erfolgt in der gewünschten Reihenfolge.

Leerzeichen und Kommas in der Eingabe werden nicht unterstützt.

Golf Version

f=function(a,b){s=substr;l=list(E='^',M='*',D='/',A='+',S='-');q="<&|~?";for(i in 1:5){x=s(q,i,i);y=l[[s(a,i,i)]];assign(x,.Primitive(y));b=gsub(y,x,b,,,T)};eval(parse(text=b))}

Ungolfed und kommentiert:

f = function(a,b) {
  s = substr
  # All arithmetic operators
  l = list(E = '^', M = '*', D = '/', A = '+', S = '-')
  # Some non-arithmetic R operators in descending precedence
  q = "<&|~?"
  for (i in 1:5) {
    # The substituted symbol
    x = s(q, i, i)
    # The original operator which has to be substituted
    y = l[[s(a, i, i)]]
    # Substitute the operator for the R interpreter
    assign(x, .Primitive(y))
    # Substitute the operator in the input string
    b = gsub(y, x, b, , , T)
  }
  # Parse and evaluate
  eval(parse(text = b))
}

Beispiele:

> f("EMDAS", "3+6*2/4-1")
[1] 5
> f("DAMES", "3+6*2/4-1")
[1] 3.5
> f("SADME", "3+6*2/4-1")
[1] 6
> f("MEADS", "3+5^4/2-3*2")
[1] 308
> f("AMEDS", "4*3-sin(0.5^2)*3+1")
[1] 11.01038
> f("DAMES", "4-5-6")
[1] -7
Patrick Roocks
quelle