StackyMath'i yorumlayın!


14

Yeni yığın tabanlı dilimi uygulama zamanı! Adı StackyMath. Bu, yığında 8 işlem ve yığına sayı eklemenin yolları olan yığın tabanlı bir dil olacaktır.

İşlemler listesi:

  • /: Bölünme. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter.
  • *: Çarpma işlemi. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter
  • -: Çıkarma. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter
  • +: İlave. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter
  • ^: Üs. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter
  • %: Modulo. Yığının ilk 2 sayısında gerçekleştirilir. Sonucu yığına geri iter
  • !: Faktöriyel. Yığının en üstündeki numarada gerçekleştirilir. Sonucu yığına geri iter
  • D: Yığında en üstteki sayıyı çoğalt

Sahte kodda tanımlanan işlemler:

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

Sayılar yığına nasıl aktarılır:

Yığına sayı eklemek kolaydır, ham sayıyı ihtiyacınız olan yere programınıza koyun. Yığına birden fazla sayı koymanız gerekirse, bunları virgülle ( ,) ayırabilirsiniz . Programınızın -girişteki sayıları işlemesine gerek yoktur , Kullanıcı bir tane isterse, negatif, sıfır ve istediği sayıyı itmelidir -. Program girişindeki sayılar da pozitif tamsayılarla sınırlıdır.

Giriş:

Programınız girdiyi komut satırından veya std girişinden almalıdır. Giriş yalnızca ,gerektiğinde sınırlanan sayılardan (bilimsel gösterim veya ondalık sayılar olmadan) ve yukarıda tanımlanan işlemlerden oluşur.

Çıktı:

Programınız numarayı yığının üstüne yazmalıdır.

Hata durumları:

  • Program yığını aşırı doldurmaya çalışırsa, yazdırmalısınız StackUnderflowException!!!.
  • Sıfıra bölme işleminiz varsa yazdırın DivisionByZeroException!!!
  • Programı yürütürken veya girişteki bir sayıyı işlerken 64 biti geçen bir sayı varsa, NumberOverflowException!!!
  • Bir şekilde yığının üstünde negatif bir sayı alırsanız ve bir faktöriyel yapmanız gerekiyorsa, yazdırın NegativeFactorialException!!!
  • Yığının üstünde bir kayan nokta numaranız varsa ve bir sonraki işlem faktöriyelse, FloatingFactorialException!!!
  • Program çıkarken (örn. Program boşken) yığınta sayı yoksa yazdırma EmptyProgram!!!

Notlar:

  • Tüm hata çıkışı yo std err veya en yakın eşdeğeri olmalıdır.
  • Tüm sayılar 64 bit kayan nokta ile sınırlıdır.

Örnek programlar:

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

(Gerekirse daha fazlasını ekleyebilirim)


3
O hata durumlarda olmasaydı, Vitsy (dönüştürme dışında doğal olarak bu yapabileceğini !için F).
Addison Crump

Kısmen, bu yüzden onları dahil ettim.
J Atkin

3
Sizinki kapsamı biraz daha geniş, ancak bunun bir kopyası olduğu iddia edilebilir: codegolf.stackexchange.com/questions/221/…
Digital Trauma

Vay canına, bunu unuttum. Ancak hataları işlemeniz gerektiğinden ve benimkinde daha fazla operatör tanımlandığından, bunların çift olduğunu düşünmüyorum.
J Atkin

654,489,48,43/5*7D+-*%dönmelidir 77.6875. ( 43/48*5-(7+7)olması gerekir (7+7)-43/48*5)
user81655

Yanıtlar:


4

Yakut, 412 410 404 392 380 377 karakter

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

Bu düzenli hassas versiyonu kullanarak Float. Sonuç hassasiyeti örnek koddaki gibidir, ancak sayısal taşma tespiti tam değildir.

Örnek çalışma:

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

Ruby, 378377 karakter

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

Bu yüksek hassasiyetli versiyonudur Rational. Sonuç hassasiyeti her zaman örnek koddakiyle aynı değildir, ancak sayısal taşma tespiti doğrudur.

Örnek çalışma:

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

3

JavaScript (ES6), 430 bayt

Değiştirerek ES7 ile 422 bayt Math.pow(2,2)için2**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!!!`

açıklama

Kullanımları evalbazı ortak ifadeler yerine. Ungolfed ve onsuz evalböyle görünüyor:

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

Eğer ES7 yükseltmek istiyorsanız şunu kullanabilirsiniz ES7 üs alma operatörü değiştirmeyi Math.pow(p(),p())ile p()**p().
usandfriends

1
@usandfriends Ben bunu düşünüyordum, ama bu benim tarayıcımda işe yaramayacağı anlamına geliyordu, bu yüzden dışarıda bıraktım. : P Bunu söyleyen bir not ekleyeceğim.
user81655

1

Groovy, 718 bayt. Fore!

Benim impl golf sonrası sonrası olabilir. Büyük kod duvarımla tanışın:

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

Düzenleme 1: @Doorknob sayesinde ~ 15 bayt tasarruf edin
Düzenleme 2: birkaç numara ile ~ 130 bayt bırakın


Groovy'yi bilmiyorum, ama çok fazla gereksiz boşluk var gibi görünüyor. Örneğin, operatörlerin etrafında, sonra for/ if, vb.
Kapı tokmağı

Hata!, Boşluk kaldırmak için daha birçok yer fark ettim. Bahşiş için teşekkürler.
J Atkin

Bunun System.in.textyerine kullanabilirsiniz System.in.newReader().readLine().
Spaghetto

Pek sayılmaz. .textaçgözlüdür ve okuyucudaki veriler olduğu sürece geri dönmez.
J Atkin

Doğru, ama bu kod golfü. İnsanların girdilerinden sonra Control-D yazmak zorunda kalmaları büyük bir sorun değildir.
spaghetto

1

Şeker , 298 348 392 bayt

Candy yığın tabanlı olmasına rağmen, gerçekten yardımcı olduğuna emin değilim ...

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

Biraz biçimlendirildiğinde biraz yapı ortaya çıkar:

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

Gerçek matematik son iki satırda gerçekleşir. Orada üçüncü hatta bir atlama masası ile sürülüyor.


Dang, DivisionByZero, NegativeFactorial ve Overflow'u kaçırdığımı görüyorum. Sadece test vakalarına bakıyordum!
Dale Johnson

Vay canına, bu harika. Sadece şekere bakmam gerekebilir.
J Atkin

Hala taşmayı tam olarak nasıl tanımlayacağım üzerinde çalışıyorum .
Dale Johnson

Aslında cevabımda da aynı problem vardı. Cevabımın altındaki yorumlara bakın.
J Atkin

Taşma işlemi şimdi düzeltildi. Her işlemin sonunda 2 ^ 64 ile karşılaştırmak için Ruby ile aynı yaklaşımı kullandım.
Dale Johnson
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.