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.