Giải thích StackyMath!


14

Thời gian để bạn thực hiện ngôn ngữ dựa trên ngăn xếp mới của tôi! Nó được gọi là StackyMath. Đây sẽ là một ngôn ngữ dựa trên ngăn xếp với 8 thao tác trên ngăn xếp và các cách để thêm số vào ngăn xếp.

Danh sách các hoạt động:

  • /: Phòng. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp.
  • *: Phép nhân. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • -: Phép trừ. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • +: Thêm vào. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • ^: Lũy thừa. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • %: Modulo. Thực hiện trên 2 số trên cùng của ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • !: Yếu tố. Thực hiện trên số đầu trên ngăn xếp. Đẩy kết quả trở lại trên ngăn xếp
  • D: Sao y số trên cùng trên ngăn xếp

Các hoạt động được xác định trong mã giả:

  • /: 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)

Cách đẩy số vào ngăn xếp:

Thêm số vào ngăn xếp rất dễ dàng, chỉ cần đặt số nguyên trong chương trình của bạn ở nơi bạn cần. Nếu bạn cần đặt nhiều số trên ngăn xếp, bạn có thể tách chúng bằng dấu phẩy ( ,). Chương trình của bạn sẽ không cần xử lý các -số trong đầu vào, Nếu người dùng muốn một số họ nên đẩy số họ muốn phủ định, 0 và- . Các số trong đầu vào của chương trình cũng bị hạn chế đối với các số nguyên dương.

Đầu vào:

Chương trình của bạn nên lấy đầu vào trên dòng lệnh hoặc từ std in. Đầu vào sẽ chỉ bao gồm các số (không có ký hiệu khoa học hoặc số thập phân) được phân cách bởi , khi cần và các thao tác được xác định ở trên.

Đầu ra:

Chương trình của bạn nên in số trên đầu ngăn xếp.

Các trường hợp lỗi:

  • Nếu chương trình cố gắng bật quá nhiều ngăn xếp, bạn nên in StackUnderflowException!!! .
  • Nếu bạn có số chia cho 0, hãy in DivisionByZeroException!!!
  • Nếu một số vượt quá 64 bit, trong khi thực hiện chương trình hoặc xử lý một số trong đầu vào, hãy in NumberOverflowException!!!
  • Nếu bằng cách nào đó bạn nhận được một số âm trên đầu ngăn xếp và bạn cần làm một giai thừa, in NegativeFactorialException!!!
  • Nếu bạn có số dấu phẩy động trên đỉnh của ngăn xếp và thao tác tiếp theo là giai thừa, hãy in FloatingFactorialException!!!
  • Nếu không có số nào trên ngăn xếp khi chương trình thoát (tức là chương trình trống) in EmptyProgram!!!

Ghi chú:

  • Tất cả đầu ra lỗi sẽ có yo std err hoặc tương đương gần nhất.
  • Tất cả các số bị giới hạn ở điểm nổi 64 bit.

Chương trình ví dụ:

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

(Tôi có thể thêm nhiều hơn nếu cần)


3
Nếu không có trong các trường hợp Lỗi, Vitsy có thể thực hiện việc này một cách tự nhiên (ngoại trừ chuyển đổi !sang F).
Addison Crump

Tôi hình dung, đó là một phần lý do tại sao tôi bao gồm chúng.
J Atkin

3
Phạm vi của bạn có phần rộng hơn, mặc dù có thể cho rằng đó là một bản sao: codegolf.stackexchange.com/questions/221/ Ấn
Chấn thương kỹ thuật số

Wow, tôi quên mất cái đó Nhưng tôi không nghĩ chúng là bản sao vì bạn phải xử lý lỗi và nhiều toán tử được xác định trong tôi.
J Atkin

654,489,48,43/5*7D+-*%nên trở về 77.6875. ( 43/48*5-(7+7)nên là (7+7)-43/48*5)
user81655

Câu trả lời:


4

Ruby, 412 410 404 392 380 377 ký tự

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

Đây là phiên bản chính xác thông thường sử dụng Float . Độ chính xác của kết quả là như trong mã mẫu, nhưng phát hiện tràn số không chính xác.

Chạy mẫu:

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

Ruby, 378 377 ký tự

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

Đây là phiên bản có độ chính xác cao sử dụng Rational. Độ chính xác của kết quả không phải lúc nào cũng giống như trong mã mẫu, nhưng phát hiện tràn số là chính xác.

Chạy mẫu:

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

3

JavaScript (ES6), 430 byte

422 byte với ES7 bằng cách thay đổi Math.pow(2,2)thành2**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!!!`

Giải trình

Sử dụng evalđể thay thế một số cụm từ phổ biến. Ungolfed và không có evalnó trông như thế này:

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

Nếu bạn muốn nâng cấp lên ES7, bạn có thể sử dụng các toán tử ES7 lũy thừa để thay thế Math.pow(p(),p())với p()**p().
tôi

1
@usandfriends Tôi đã suy nghĩ về nó, nhưng điều đó có nghĩa là nó không hoạt động trong trình duyệt của tôi nên tôi đã bỏ nó. : P Tôi sẽ thêm một ghi chú nói rằng.
dùng81655

1

Groovy, 718 byte. Trán!

Cũng có thể gửi bài impl của tôi. Gặp bức tường mã lớn của tôi:

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!!!')

Ung dung:

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!!!')

Chỉnh sửa 1: lưu ~ 15 byte nhờ @Doorknob
Chỉnh sửa 2: thả ~ 130 byte với một vài thủ thuật nữa


Tôi không biết Groovy, nhưng dường như bạn có rất nhiều khoảng trắng không cần thiết. Ví dụ: xung quanh các nhà khai thác, sau for/ if, v.v.
Doorknob

Rất tiếc, chỉ cần chú ý nhiều nơi hơn để xóa khoảng trắng. Cảm ơn vì tiền hỗ trợ.
J Atkin

Bạn có thể sử dụng System.in.textthay vì System.in.newReader().readLine().
một spaghetto

Không hẳn vậy. .textlà tham lam và miễn là dữ liệu trong trình đọc, nó sẽ không trở lại.
J Atkin

Phải, nhưng đây là mã golf. Đó không phải là vấn đề lớn nếu mọi người phải gõ Control-D sau đầu vào của họ.
một spaghetto

1

Kẹo , 298 348 392 byte

Mặc dù Candy dựa trên stack, tôi không chắc điều đó thực sự có ích ...

&{|"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*).

Định dạng một chút cho thấy một chút cấu trúc:

&{|"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*).

Toán học thực tế xảy ra trên hai dòng cuối cùng. Nó được điều khiển bởi một bàn nhảy trên dòng thứ ba.


Dang, tôi thấy rằng tôi đã bỏ lỡ DivisionByZero, NegativeFactorial và Overflow. Tôi chỉ nhìn vào các trường hợp thử nghiệm!
Dale Johnson

Wow, điều này thật tuyệt Tôi chỉ cần tìm kẹo.
J Atkin

Tôi vẫn đang làm việc về cách xác định chính xác tràn.
Dale Johnson

Thật ra tôi đã có cùng một vấn đề trong câu trả lời của mình. Xem các ý kiến ​​dưới câu trả lời của tôi.
J Atkin

Đã sửa lỗi tràn bây giờ. Tôi đã sử dụng cách tiếp cận tương tự như Ruby, chỉ để so sánh với 2 ^ 64 ở cuối mỗi thao tác.
Dale Johnson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.