Dames, lakukan matematika!

19

Urutan operasi, PEMDAS, adalah aturan dasar dalam matematika yang memberitahu kita operasi urutan mana yang harus dilakukan:

"Kurung, Eksponen, Penggandaan dan Pembagian, dan Penambahan dan Pengurangan"

Masalahnya, PEMDAS tidak terlalu fleksibel! Bagaimana jika Anda ingin melakukannya dengan urutan lain? Kami tidak akan mengacaukan dengan tanda kurung, jadi kami menyimpannya di tempat mereka (pertama).

Buat program yang membutuhkan dua argumen:

  • Sebuah string, memberi tahu urutan operasi yang harus diikuti. Beberapa contoh adalah "DAMES", "SAD, ME", "ME SAD", "MEADS". Ya, spasi dan koma OK, karena membuat urutan lebih mudah diingat.
    • Saran berikut dalam obrolan: Ruang pendukung dan koma sekarang opsional.
    • Jika salah satu surat hilang, atau jika ada surat tambahan yang seharusnya tidak ada, Anda dapat menganggap input tidak valid dan memperlakukannya sesuka Anda.
  • String, atau ekspresi yang mengandung ekspresi yang harus dievaluasi.

Kembalikan hasil ekspresi sebagai angka desimal, atau bilangan bulat. Jika jawabannya bukan bilangan bulat, harus dikembalikan sebagai angka desimal.

Aturan:

  • Tidak apa-apa untuk menggabungkan dua argumen input menjadi satu, jika itu lebih mudah dalam bahasa Anda.
  • Tidak harus berupa string, tetapi harus memiliki huruf. Anda tidak dapat mengganti Penambahan dengan 1, Divisi dengan 2, dll.
  • Anda dapat memilih input mana yang lebih dulu.
  • Ekspresi dievaluasi dari kanan ke kiri ke kanan. (Perubahan aturan. Setiap poster yang dikirim 12 jam pertama yang menerima ini sebaliknya diterima).
  • Operasi menggunakan simbol-simbol: ( ) ^ * / + -. Misalnya, Anda tidak dapat menggunakan ¤alih-alih +untuk penambahan.
  • Spasi dalam ekspresi input tidak valid sebagai input
  • Unary +/- tidak valid sebagai input jika langsung mengikuti + atau -. Pertimbangkan 3+-2sebagai input yang tidak valid. Itu dapat diperlakukan sesuka Anda (tidak harus menghasilkan kesalahan). Jika +atau -mengikuti operator lain selain plus atau minus, itu diperlakukan dengan cara yang biasa: 3*-3 = -9,sin(-2)=-0.909
  • Program harus benar-benar mengikuti huruf, jadi "EMDAS", 1-3+4 => -6, dan "EMDSA", 1-3+4 => 2.

Contoh:

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

Catatan, tanda kurung di mana ditambahkan untuk menunjukkan bahwa perkalian 4*sin(0.5^2)dievaluasi sebelum eksponensial.

Ini adalah kode golf, jadi kode terpendek dalam byte menang.

Stewie Griffin
sumber
2
Sama sekali tidak sama, tetapi tantangan ini adalah tentang mengubah urutan operasi lain dan merupakan inspirasi yang membuat saya menyukai gagasan melakukan sesuatu yang serupa. Saya pikir jawaban Haskell dapat bekerja kembali untuk menjawab pertanyaan ini mungkin ... Tidak yakin jika duplikat yang ketat, saya cukup menyukai ide melakukan tantangan ini tanpa kemampuan asli untuk mengubah operator secara langsung!
Dom Hastings
2
Bonus untuk fungsi dihapus, tetapi masih ada sin () dalam contoh.
edc65
Agak lebih jahat daripada tantangan yang disebutkan di atas, dan saya tidak akan menganggapnya sebagai duplikat (meskipun tautan ke aslinya akan dihargai). Namun, jelas bagi semua orang untuk melihat sutradara jahat The 2560 tidak lain adalah @Stewie Griffin. Saya harus mengatakan, saya tidak terkejut.
Jake
Di Inggris kita sering diajarkan sebagai BODMASatau BIDMASdi sekolah. B= Kurung, Oatau I= Pesan atau Indeks.
BadHorsie
Apakah pdibutuhkan? Itu tidak ada dalam contoh
ev3commander

Jawaban:

7

JavaScript (ES6) 349 353 387 400

... mungkin masih golf

Pengurai lama saya ini kadang berguna - (sudah digunakan dalam 2 tantangan lainnya)

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>

Tidak disatukan

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
sumber
Saya pikir Anda dapat menghapus ruang (t=>t=='('?(z=1, Q.push('_')), bersama dengan semua baris baru.
Conor O'Brien
1
@ CᴏɴᴏʀO'Bʀɪᴇɴ sedang mengerjakannya. Terima kasih
edc65
Saya pikir Anda dapat mengubah Math.pow(a,b)kea**b
Kritixi Lithos
@KritixiLithos ya tapi itu tidak akan menjadi ES6 lagi
edc65
6

R 3.3.2: 209 196 187 177 bytes

Idenya adalah untuk "menyalahgunakan" operator non-aritmatika <, &, |, ~,? di mana kita tahu diutamakan (lihat ?Syntaxdi R - tetapi sebelum menimpa;)) dan menimpa mereka dengan operator aritmatika yang diberikan. Pemetaan sesuai dengan urutan operasi yang diinginkan.

Spasi dan koma pada input tidak didukung.

Versi golf

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

Tidak dikumpulkan dan berkomentar:

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

Contoh:

> 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
sumber