ตีความ StackyMath!


14

ถึงเวลาที่คุณจะใช้ภาษาสแต็กใหม่ของฉัน! มันเรียกว่า StackyMath นี่จะเป็นภาษาแบบสแต็กที่มีการดำเนินการ 8 รายการบนสแต็กและวิธีเพิ่มหมายเลขในสแต็ก

รายการของการดำเนินงาน:

  • /: แผนก. ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • *: การคูณ ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • -: การลบ ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • +: ส่วนที่เพิ่มเข้าไป. ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • ^: การยกกำลัง ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • %: Modulo ดำเนินการกับตัวเลข 2 อันดับแรกของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • !: แฟคทอเรียล ดำเนินการกับหมายเลขบนสุดของสแต็ก ผลักผลลัพธ์กลับคืนบนสแต็ก
  • D: ทำซ้ำหมายเลขบนสุดของสแต็ก

การดำเนินการที่กำหนดไว้ในรหัสหลอก:

  • /: push(pop divided by pop)
  • *: push(pop times pop)
  • -: push(pop minus pop)
  • +: push(pop plus pop)
  • ^: push(pop to the pop)
  • %: push(pop mod pop)
  • !: push(factorial pop)
  • D: t = pop; push(t); push(t)

วิธีใส่ตัวเลขลงในสแต็ก:

การเพิ่มหมายเลขลงในสแต็กนั้นง่ายเพียงแค่ใส่หมายเลขดิบลงในโปรแกรมที่คุณต้องการ หากคุณต้องการใส่ตัวเลขจำนวนมากในสแต็กคุณสามารถแยกพวกเขาด้วยเครื่องหมายจุลภาค ( ,) โปรแกรมของคุณจะไม่จำเป็นต้องกระบวนการตัวเลขในการป้อนข้อมูลหากผู้ใช้ต้องการหนึ่งที่พวกเขาควรจะผลักดันจำนวนที่พวกเขาต้องการทำให้ไร้ผลศูนย์และ- -ตัวเลขในอินพุตของโปรแกรมยังถูก จำกัด ด้วยจำนวนเต็มบวก

การป้อนข้อมูล:

โปรแกรมของคุณควรใช้อินพุตในบรรทัดคำสั่งหรือจาก std in อินพุตจะประกอบด้วยตัวเลขเท่านั้น (ไม่มีเครื่องหมายทางวิทยาศาสตร์หรือทศนิยม) คั่นด้วย ,ที่จำเป็น

เอาท์พุท:

โปรแกรมของคุณควรพิมพ์หมายเลขที่ด้านบนสุดของสแต็ก

กรณีข้อผิดพลาด:

  • StackUnderflowException!!!หากโปรแกรมพยายามมากกว่าป๊อปสแต็คที่คุณควรพิมพ์
  • หากคุณมีการหารด้วยศูนย์ให้พิมพ์ DivisionByZeroException!!!
  • หากตัวเลขที่เกิน 64- บิตไม่ว่าจะเป็นการรันโปรแกรมหรือประมวลผลตัวเลขในอินพุตให้พิมพ์ NumberOverflowException!!!
  • หากคุณได้จำนวนลบที่ด้านบนสุดของสแต็กและคุณต้องทำแฟกทอเรียลให้พิมพ์ NegativeFactorialException!!!
  • หากคุณมีหมายเลขจุดลอยตัวที่ส่วนบนสุดของสแต็กและการดำเนินการต่อไปคือแฟคทอเรียลให้พิมพ์ FloatingFactorialException!!!
  • หากไม่มีตัวเลขอยู่ในสแต็กเมื่อโปรแกรมออก (เช่นโปรแกรมว่างเปล่า) พิมพ์ EmptyProgram!!!

หมายเหตุ:

  • ข้อผิดพลาดทั้งหมดที่ส่งออกไปควรมีข้อผิดพลาดหรือใกล้เคียงที่สุด
  • ตัวเลขทั้งหมดถูก จำกัด ให้เป็นทศนิยม 64 บิต

โปรแกรมตัวอย่าง:

50,47*                 -> 2350
50,47/                 -> 0.94
100,8!                 -> 40320  
100D*                  -> 10000
!                      -> StackUnderflowException!!!
5,2/!                  -> FloatingFactorialException!!!  
4,3!2*/                -> 3 
654,489,48,43/5*7D+-*% -> 77.68749999999909
                       -> EmptyProgram!!!

(ฉันสามารถเพิ่มมากขึ้นถ้าจำเป็น)


3
หากไม่ใช่ในกรณีที่เกิดข้อผิดพลาดVitsyสามารถทำได้ตามปกติ (ยกเว้นการแปลง!เป็นF)
Addison Crump

ฉันคิดว่านั่นเป็นส่วนหนึ่งที่ฉันรวมไว้
J Atkin

3
ของคุณค่อนข้างกว้างในขอบเขตแม้ว่ามันอาจจะพิสูจน์ได้ว่ามันซ้ำกัน: codegolf.stackexchange.com/questions/221/…
Digital Trauma

ว้าวฉันลืมเรื่องนั้นไป แต่ฉันไม่คิดว่ามันเป็นเรื่องหลอกเพราะคุณต้องประมวลผลข้อผิดพลาดและมีการกำหนดโอเปอเรเตอร์เพิ่มขึ้นในเหมือง
J Atkin

654,489,48,43/5*7D+-*%77.6875ควรกลับ ( 43/48*5-(7+7)ควรเป็น(7+7)-43/48*5)
user81655

คำตอบ:


4

Ruby, 412 410 404 392 380 377 ตัวอักษร

def e m,x='Exception';warn m+x+?!*3;exit;end
def o;e'StackUnderflow'if$*==[];$*.pop;end
u=->n{e'DivisionByZero'if n.infinite?;e'NumberOverflow'if n>2**64;$*<<n}
f=->n{e'NegativeFactorial'if n<0;e'FloatingFactorial'if n.to_i<n;n<2?1:f[n-1]*n}
gets.gsub(/(\d+)|([+*\/%^-])|(!)|D/){$1?u[$1.to_f]:$2?u[eval"o#{$2>?A?:**:$2}o"]:$3?u[f[o]]:u[x=o]+u[x]}
e'EmptyProgram',''if$*==[]
p o

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

วิ่งตัวอย่าง:

bash-4.3$ ruby StackyMath.rb <<< '654,489,48,43/5*7D+-*%'
77.68749999999909

Ruby, 378 377 ตัวอักษร

def e m,x='Exception';warn m+x+?!*3;exit;end
def o;e'StackUnderflow'if$*==[];$*.pop;end
u=->n{e'NumberOverflow'if n>2**64;$*<<n}
f=->n{e'NegativeFactorial'if n<0;e'FloatingFactorial'if n.to_i<n;n<2?1:f[n-1]*n}
gets.gsub(/(\d+)|([+*\/%^-])|(!)|D/){$1?u[Rational$1]:$2?u[eval"o#{$2>?A?:**:$2}o"]:$3?u[f[o]]:u[x=o]+u[x]}rescue e'DivisionByZero'
e'EmptyProgram',''if$*==[]
p o.to_f

นี่เป็นรุ่นที่มีความแม่นยำสูงโดยใช้ Rationalนี้เป็นรุ่นที่มีความแม่นยำสูงโดยใช้ความแม่นยำของผลลัพธ์ไม่เหมือนกับรหัสตัวอย่างเสมอไป แต่การตรวจจับการล้นของตัวเลขเป็นสิ่งที่แน่นอน

วิ่งตัวอย่าง:

bash-4.3$ ruby StackyMath-hi.rb <<< '654,489,48,43/5*7D+-*%'
77.6875

3

JavaScript (ES6), 430 ไบต์

422 ไบต์ด้วย ES7 โดยเปลี่ยนMath.pow(2,2)เป็น2**2

e=m=>{throw alert(m)};u=prompt();u?alert(eval('u.match(/\\d+|[^,]/g).map(o=>s.push(t=o=="/"?(b=p(a=2))?a/b:e`DivisionByZero43*"?2*23-"?2-23+"?2+23%"?2%23^"?Math.pow(2,2)3D"?s.push(r=2)&&r3!"?eval("for(r=i=2;i<0?e`Negative54:i%1?e`Floating54:--i;)r*=i;r"):+o)&&t==Infinity&&e`NumberOverflow4,s=[],p=_=>s.length?s.pop():e`StackUnderflow4);t'.replace(/[2-5]/g,x=>[,,'p()',':o=="','Exception!!!`','Factorial'][x]))):e`EmptyProgram!!!`

คำอธิบาย

ใช้evalเพื่อแทนที่วลีทั่วไปบางอย่าง Ungolfed และไม่มีevalลักษณะเช่นนี้:

e=m=>{throw alert(m)};                           // e = throw error, alert displays
                                                 //     message, throw stops execution
u=prompt();                                      // u = received input
u?alert(                                         // display the result
  u.match(/\d+|[^,]/g)                           // get array of numbers and operators
    .map(o=>                                     // iterate over operators
      s.push(t=                                  // t = last pushed value

        // Execute operator
        o=="/"?(b=p(a=p()))?a/b:                 // make sure argument B is not 0
          e`DivisionByZeroException!!!`:
        o=="*"?p()*p():
        o=="-"?p()-p():
        o=="+"?p()+p():
        o=="%"?p()%p():
        o=="^"?Math.pow(p(),p()):
        o=="D"?s.push(r=p())&&r:
        o=="!"?eval("                            // eval to enable for loop in ternary
          for(                                   // no factorial in JS so do this manually
            r=i=p();
            i<0?e`NegativeFactorialException!!!` // check for errors
              :i%1?
                e`FloatingFactorialException!!!`
                :--i;
          )
            r*=i;
          r"):                                   // return r
        +o                                       // if not an operator cast as a number
      )&&t==Infinity&&                           // JS turns anything over 64 bit float
        e`NumberOverflowException!!!`,           //     max value into Infinity
      s=[],                                      // s = stack array
      p=_=>s.length?s.pop():                     // p = check stack then pop
        e`StackUnderflowException!!!`
    )&&t                                         // return top stack element
  ):e`EmptyProgram!!!`                           // error if input length is 0

ถ้าคุณต้องการอัพเกรด ES7 คุณสามารถใช้ประกอบการ ES7 ยกกำลังที่จะเปลี่ยนด้วยMath.pow(p(),p()) p()**p()
usandfriends

1
@ แฟนฉันกำลังคิดเกี่ยวกับมัน แต่มันหมายความว่ามันจะไม่ทำงานในเบราว์เซอร์ของฉันดังนั้นฉันทิ้งมันไว้ : P ฉันจะเพิ่มบันทึกที่บอกว่า
user81655

1

Groovy ขนาด 718 ไบต์ Fore!

อาจโพสต์ impl ของฉัน golfed พบกับกำแพงรหัสขนาดใหญ่ของฉัน:

g='Exception!!!'
a={System.err.print(it);System.exit(1)}
b=new Stack()
c={b.push(it)}
v=2d**64d
d={b.pop()}
e={if(b.size()<it)a('StackUnderflow'+g)}
f={a('NumberOverflow'+g)}
h={e(2)
c(Eval.xy(d(),d(),"x$it y"))
if(b.peek()>v)f()}
k={i->if(i<0)a('NegativeFactorial'+g)
if(Math.abs(i-(i as long))>1E-6)a('FloatingFactorial'+g)
(2..i).inject{x,y->(v/x<y)?f():x*y}}
l=['/':{e(2)
m=d()
n=d()
if(n==0)a('DivisionByZero'+g)
c(m/n)},'!':{e(1)
c(k(d()))},'D':{e(1)
c(b.peek())}]
System.in.newReader().readLine().findAll(~/\d+|[^,]/).each{x->if(x.matches(/\d+/))try{c(x as double)}catch(Exception e){f()}
else if("+-*%^".contains(x))h(x.replace('^','**'))
else l[x]()}
if(b){o=d()
if(Double.isInfinite(o))f()
println o}else a('EmptyProgram!!!')

Ungolfed:

error = {System.err.print(it);System.exit(1)}

stack = new Stack()
maxVal = 2d**64d

push = {stack.push(it)}
pop = {stack.pop()}

checkAtLeast = {if (stack.size() < it) error('StackUnderflow'+exception)}
numberOverflow = {error('NumberOverflow'+exception)}

exception = 'Exception!!!'

def dArgOp(i) {
    checkAtLeast(2)
    push(Eval.xy(pop(), pop(), "x$i y"))
    if(stack.peek() > maxVal) numberOverflow
}

factorial = {i->
    if (i < 0)
        error('NegativeFactorial'+exception)
    if (Math.abs(i - (i as long)) > 1E-6)
        error('FloatingFactorial'+exception)
    (2..i).inject {acc, it ->
        (maxVal/acc < it)?numberOverflow():acc*it
    }
}

ops = [
'/' : {
    checkAtLeast(2)
    first = pop()
    second = pop()
    if (second == 0)
        error('DivisionByZero'+exception)
    push(first / second)
},
'!' : {
    checkAtLeast(1)
    push(factorial(pop()))
},
'D' : {
    checkAtLeast(1)
    push(stack.peek())
}]

input = System.in.newReader().readLine()
tokens = input.findAll(~/\d+|[^,]/)

tokens.each {
    print "current token: $it  \t stack before eval: $stack "
    if (it.matches(/\d+/))
        try {
            push(it as double)
        } catch (Exception e) {
            numberOverflow()
        }

    else if ("+-*%^".contains(it))
        dArgOp(it.replace('^','**'))
    else
        ops[it]()
    println "result: ${stack.peek()}"
}

if (stack) {
    top = pop()
    if (Double.isInfinite(top))
        numberOverflow()
    println top
} else
    error('EmptyProgram!!!')

แก้ไข 1: บันทึก ~ 15 ไบต์ขอบคุณ @Doorknob
แก้ไข 2: วาง ~ 130 ไบต์พร้อมกับลูกเล่นเพิ่มเติม


ฉันไม่รู้จัก Groovy แต่ดูเหมือนว่าคุณมีช่องว่างที่ไม่จำเป็นจำนวนมาก ตัวอย่างเช่นรอบตัวดำเนินการหลังfor/ ifฯลฯ
Doorknob

อ๊ะเพิ่งสังเกตเห็นอีกหลายแห่งเพื่อลบช่องว่างออก ขอบคุณสำหรับทิป.
J Atkin

คุณสามารถใช้แทนSystem.in.text System.in.newReader().readLine()
ปาเก็ตตี้

ไม่ได้จริงๆ .textโลภมากและตราบใดที่ข้อมูลในเครื่องอ่านมันจะไม่ส่งคืน
J Atkin

ใช่ แต่นี่คือรหัสกอล์ฟ ไม่ใช่เรื่องใหญ่หากผู้คนต้องพิมพ์ Control-D หลังจากป้อนข้อมูล
ปาเก็ตตี้

1

แคนดี้ , 298 348 392 ไบต์

แม้ว่า Candy จะเป็นกองซ้อน แต่ฉันไม่แน่ใจว่าช่วยได้จริง ...

&{|"EmptyProgram!!!\n"(;).}(=bYZay0=zx4k"!%*+,-/D^"(iYe{Z=x})aYb=z=ya=X{Y{cZ0=yza}b212202221(i=ZXe{y})a0=zcY0j{XjZ{|D1b#64R(=c2*)c>{b"NumberOverFlow"(;)i}}|i}aZ{(=)"Exception!!!\n"(;).}0=yz|A#48-Z#10*+=z1=y})c?(=).@0&<{1|b"StackUnderflow"(;)c0}.@1~ALe{A0<{b"Negative"(;)i|1bAR(=cA*)}|b"Floating"(;)i}Z{b"Factorial"(;)}.@2W%.@3*.@4+@5.@6W-.@7WD{/|b"DivisionByZero"(;)i}.@8~A.@9=xK=y=1bA_(cX*).

การจัดรูปแบบบิตเผยให้เห็นโครงสร้างเล็กน้อย:

&{|"EmptyProgram!!!\n"(;).}
(=bYZay0=zx4k
  "!%*+,-/D^"
  (iYe{Z=x})
  aYb=z=ya=X
  {
    Y{cZ0=yza}b
    212202221(i=ZXe{y})
    a0=zcY0j
    {XjZ{|D1b#64R(=c2*)c>{b"NumberOverFlow"(;)i}}|i}
    aZ{(=)"Exception!!!\n"(;).}
    0=yz|A#48-Z#10*+=z1=y
  }
)c?(=).
@0&<{1|b"StackUnderflow"(;)c0}.
@1~ALe{A0<{b"Negative"(;)i|1bAR(=cA*)}|b"Floating"(;)i}Z{"Factorial"(;)}.
@2W%.@3*.@4+@5.@6W-.@7WD{/|"DivisionByZero"(;)i}.@8~A.@9=xK=y=1bA_(cX*).

คณิตศาสตร์ที่เกิดขึ้นจริงในสองบรรทัดสุดท้าย มันขับเคลื่อนด้วยตารางกระโดดในบรรทัดที่สาม


แดงฉันเห็นว่าฉันพลาด DivisionByZero, NegativeFactorial และ Overflow ฉันแค่ดูกรณีทดสอบ!
Dale Johnson

ว้าวนี่มันเท่ห์ ฉันอาจจะต้องมองหาขนม
J Atkin

ฉันยังคงทำงานเกี่ยวกับวิธีการกำหนดล้นอย่างแน่นอน
Dale Johnson

ที่จริงฉันมีปัญหาเดียวกันในคำตอบของฉัน ดูความคิดเห็นด้านล่างคำตอบของฉัน
J Atkin

แก้ไขโอเวอร์โฟลว์ตอนนี้ ฉันใช้วิธีการเดียวกับ Ruby ซึ่งเปรียบเทียบกับ 2 ^ 64 ที่ส่วนท้ายของแต่ละการดำเนินการ
Dale Johnson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.