ท้าวทำคณิตศาสตร์!


19

ลำดับของการดำเนินการ PEMDAS เป็นกฎพื้นฐานในคณิตศาสตร์ที่บอกเราว่าควรดำเนินการตามคำสั่งอย่างไร:

"วงเล็บเลขชี้กำลังการคูณและการหารและการบวกและลบ"

ปัญหาคือ PEMDAS ไม่หลากหลายมาก! ถ้าคุณต้องการที่จะทำในลำดับอื่น เราจะไม่ยุ่งกับวงเล็บดังนั้นเราจึงเก็บมันไว้ในที่ที่มันอยู่ (อันดับแรก)

สร้างโปรแกรมที่รับสองอาร์กิวเมนต์:

  • สตริงที่บอกลำดับการดำเนินการที่ควรปฏิบัติ ตัวอย่างบางส่วน"DAMES", "SAD, ME", ,"ME SAD" "MEADS"ใช่ช่องว่างและเครื่องหมายจุลภาคก็โอเคเพราะทำให้ง่ายต่อการจดจำคำสั่ง
    • การติดตามคำแนะนำในการแชท: การสนับสนุนช่องว่างและเครื่องหมายจุลภาคเป็นทางเลือก
    • หากตัวอักษรตัวใดตัวหนึ่งหายไปหรือหากมีตัวอักษรเพิ่มเติมที่ไม่ควรอยู่ที่นั่นคุณสามารถพิจารณาอินพุตที่ไม่ถูกต้องและจัดการตามที่คุณต้องการ
  • สตริงหรือนิพจน์ที่มีนิพจน์ที่ควรได้รับการประเมิน

ส่งคืนผลลัพธ์ของนิพจน์เป็นตัวเลขทศนิยมหรือจำนวนเต็ม หากคำตอบไม่ใช่จำนวนเต็มจะต้องส่งคืนเป็นเลขทศนิยม

กฎ:

  • คุณสามารถรวมอาร์กิวเมนต์ที่ป้อนเข้าสองรายการเข้าเป็นหนึ่งเดียวได้ถ้าหากในภาษาของคุณง่ายขึ้น
  • ไม่จำเป็นต้องเป็นสตริง แต่ต้องมีตัวอักษร คุณไม่สามารถทดแทนการเพิ่มด้วย 1, หารด้วย 2, เป็นต้น
  • คุณสามารถเลือกอินพุตที่เป็นอันดับแรก
  • นิพจน์ได้รับการประเมินจากขวาไปซ้ายจากซ้ายไปขวา (การเปลี่ยนแปลงของกฎโปสเตอร์ที่ส่งใด ๆ ใน 12 ชั่วโมงแรกที่มีวิธีอื่น ๆ ได้รับการยอมรับ)
  • ( ) ^ * / + -การดำเนินงานของใช้สัญลักษณ์นี้: ตัวอย่างเช่นคุณไม่สามารถใช้¤แทน+การเพิ่มได้
  • ช่องว่างในนิพจน์อินพุตไม่ถูกต้องเป็นอินพุต
  • Unary +/- ไม่ถูกต้องเป็นอินพุตถ้ามันตรงตาม + หรือ - พิจารณา3+-2ว่าเป็นอินพุตที่ไม่ถูกต้อง สามารถรักษาได้ตามที่คุณต้องการ (ไม่ต้องมีข้อผิดพลาด) หาก+หรือ-ติดตามตัวดำเนินการอื่นที่ไม่ใช่บวกหรือลบจะถือว่าเป็นวิธีปกติ: 3*-3 = -9,sin(-2)=-0.909
  • โปรแกรมที่จะต้องปฏิบัติตามอย่างเคร่งครัดตัวอักษรเพื่อให้และ"EMDAS", 1-3+4 => -6"EMDSA", 1-3+4 => 2

ตัวอย่าง:

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

หมายเหตุวงเล็บที่เพิ่มเพื่อแสดงว่าการคูณ4*sin(0.5^2)จะถูกประเมินก่อนการยกกำลัง

นี่คือรหัสกอล์ฟดังนั้นรหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


2
มันไม่เหมือนกันทุกประการแต่ความท้าทายนี้เกี่ยวกับการเปลี่ยนไปสู่การดำเนินการอื่นและเป็นแรงบันดาลใจที่ทำให้ฉันชอบความคิดในการทำสิ่งที่คล้ายกัน ฉันคิดว่าคำตอบของ Haskell อาจจะถูกทำซ้ำเพื่อตอบคำถามนี้บางที ... ไม่แน่ใจว่าเป็นคำที่ซ้ำซ้อนหรือไม่ฉันชอบความคิดที่จะทำสิ่งนี้โดยไม่ต้องมีความสามารถในการเปลี่ยนผู้ปฏิบัติงานโดยตรง!
Dom Hastings

2
โบนัสสำหรับฟังก์ชั่นที่ลบออก แต่ยังมีบาป () ในตัวอย่าง
edc65

มีความชั่วร้ายมากกว่าความท้าทายที่กล่าวมาข้างต้นและฉันจะไม่คัดค้านว่ามันซ้ำซ้อน อย่างไรก็ตามมันเป็นเรื่องธรรมดาที่ทุกคนจะได้เห็นผู้อำนวยการชั่วร้ายของThe 2560ไม่ใช่ใครอื่นนอกจาก @Stewie Griffin ฉันต้องบอกว่าฉันไม่แปลกใจ
Jake

ในสหราชอาณาจักรเรามักจะสอนเป็นBODMASหรือBIDMASที่โรงเรียน B= วงเล็บเหลี่ยมOหรือI= คำสั่งซื้อหรือดัชนี
BadHorsie

เป็นที่pจำเป็น? มันไม่ได้อยู่ในตัวอย่าง
ev3commander

คำตอบ:


7

JavaScript (ES6) 349 353 387 400

... อาจเล่นกอล์ฟได้

ตัวแยกวิเคราะห์เก่าของฉันในบางครั้งมีประโยชน์ - (เคยใช้ใน 2 ความท้าทายอื่น ๆ แล้ว)

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>


ฉันคิดว่าคุณสามารถลบพื้นที่ใน(t=>t=='('?(z=1, Q.push('_'))พร้อมกับบรรทัดใหม่ทั้งหมด
Conor O'Brien

1
@ CᴏɴᴏʀO'Bʀɪᴇɴกำลังทำงานอยู่ ขอบคุณ
edc65

ฉันคิดว่าคุณสามารถเปลี่ยนMath.pow(a,b)ไปa**b
Kritixi Lithos

@KritixiLithos ใช่ แต่ไม่ใช่ ES6 อีกต่อไปแล้ว
edc65

6

R 3.3.2: 209 196 187 177 ไบต์

แนวคิดคือการ "ใช้ผิด" ตัวดำเนินการที่ไม่ใช่คณิตศาสตร์ <, &,, |, ~,? ที่เรารู้ว่ามีความสำคัญ (ดู?Syntaxใน R - แต่ก่อนที่จะแทนที่;) และเอาชนะพวกเขาด้วยตัวดำเนินการทางคณิตศาสตร์ที่กำหนด การทำแผนที่เป็นไปตามลำดับของการดำเนินการที่ต้องการ

ไม่รองรับช่องว่างและเครื่องหมายจุลภาคในอินพุต

รุ่น golfed

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 และแสดงความคิดเห็น:

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

ตัวอย่าง:

> 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.