# Interpret StackyMath!

Time for you to implement my new stack based language! It's called StackyMath. This will be a stack based language with 8 operations on the stack and ways to add numbers to the stack.

### List of operations:

• /: Division. Performed on the top 2 numbers of the stack. Pushes the result back on the stack.
• *: Multiplication. Performed on the top 2 numbers of the stack. Pushes the result back on the stack
• -: Subtraction. Performed on the top 2 numbers of the stack. Pushes the result back on the stack
• +: Addition. Performed on the top 2 numbers of the stack. Pushes the result back on the stack
• ^: Exponentiation. Performed on the top 2 numbers of the stack. Pushes the result back on the stack
• %: Modulo. Performed on the top 2 numbers of the stack. Pushes the result back on the stack
• !: Factorial. Performed on the top number on the stack. Pushes the result back on the stack
• D: Duplicate the top number on the stack

### Operations defined in pseudo code:

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

### How to push numbers to the stack:

Adding numbers to the stack is easy, just put the raw number in your program where you need it. If you need to put multiple numbers on the stack you can separate them with a comma (,). Your program will not need to process - numbers in the input, If the user wants one they should push the number they want negated, zero, and -. Numbers in the input of the program are also constrained to positive integers.

### Input:

Your program should take the input on the command line, or from std in. Input will only consist of numbers (no scientific notation or decimals) delimited by , as needed, and the operations defined above.

### Output:

Your program should print the number on the top of the stack.

Error cases:

• If the program tries to over-pop the stack, you should print StackUnderflowException!!! .
• If you have division by zero, print DivisionByZeroException!!!
• If a number that exceeds 64-bits, either while executing the program or processing a number in the input, print NumberOverflowException!!!
• If somehow you get a negative number on the top of the stack and you need to do a factorial, print NegativeFactorialException!!!
• If you have a floating point number on the tops of the stack and the next operation is factorial, print FloatingFactorialException!!!
• If no numbers are on the stack when the program exits (i.e. the program was empty) print EmptyProgram!!!

### Notes:

• All error output to should got yo std err or closest equivalent.
• All numbers are constrained to 64-bit floating point.

Example programs:

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


(I can add more if needed)

• If it weren't for the Error cases, Vitsy could do this naturally (except converting ! to F). Dec 2, 2015 at 20:36
• I figured, that's partly why I included them. Dec 2, 2015 at 20:37
• Yours is somewhat broader in scope, though it may be arguable that its a duplicate: codegolf.stackexchange.com/questions/221/… Dec 2, 2015 at 22:29
• Wow, I forgot about that one. But I don't think they are dupes since you have to process errors and more operators are defined in mine. Dec 2, 2015 at 23:07
• 654,489,48,43/5*7D+-*% should return 77.6875. (43/48*5-(7+7) should be (7+7)-43/48*5) Dec 3, 2015 at 1:32

# Ruby, 412410404392380 377 characters

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


This is regular precision version using Float. The result precision is as in the sample code, but numeric overflow detection is not exact.

Sample run:

bash-4.3$ruby StackyMath.rb <<< '654,489,48,43/5*7D+-*%' 77.68749999999909  ## Ruby, 378 377 characters 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  This is high precision version using Rational. The result precision is not always the same as in the sample code, but numeric overflow detection is exact. Sample run: bash-4.3$ ruby StackyMath-hi.rb <<< '654,489,48,43/5*7D+-*%'
77.6875


# JavaScript (ES6), 430 bytes

422 bytes with ES7 by changing Math.pow(2,2) to 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:eDivisionByZero43*"?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?eNegative54:i%1?eFloating54:--i;)r*=i;r"):+o)&&t==Infinity&&eNumberOverflow4,s=[],p=_=>s.length?s.pop():eStackUnderflow4);t'.replace(/[2-5]/g,x=>[,,'p()',':o=="','Exception!!!','Factorial'][x]))):eEmptyProgram!!!


## Explanation

Uses eval to replace certain common phrases. Ungolfed and without the eval it looks like this:

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
eDivisionByZeroException!!!:
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?eNegativeFactorialException!!! // check for errors
:i%1?
eFloatingFactorialException!!!
:--i;
)
r*=i;
r"):                                   // return r
+o                                       // if not an operator cast as a number
)&&t==Infinity&&                           // JS turns anything over 64 bit float
eNumberOverflowException!!!,           //     max value into Infinity
s=[],                                      // s = stack array
p=_=>s.length?s.pop():                     // p = check stack then pop
eStackUnderflowException!!!
):eEmptyProgram!!!                           // error if input length is 0

• If you want to upgrade to ES7, you could use the ES7 exponentiation operator to replace Math.pow(p(),p()) with p()**p(). Dec 3, 2015 at 4:54
• @usandfriends I was thinking about it, but it meant that it would not work in my browser so I left it out. :P I'll add a note saying that. Dec 3, 2015 at 5:07

# Groovy, 718 bytes. Fore!

May as well post my impl golfed. Meet my big wall of code:

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

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


Edit 1: save ~15 bytes thanks to @Doorknob
Edit 2: drop ~130 bytes with a few more tricks

• I don't know Groovy, but you seem to have lots of unnecessary whitespace. For example, around operators, after for/if, etc Dec 2, 2015 at 21:13
• Whoops, just noticed many more places to remove whitespace. Thanks for the tip. Dec 2, 2015 at 21:22
• You can use System.in.text instead of System.in.newReader().readLine(). Dec 3, 2015 at 0:47
• Not really. .text is greedy and as long as data in in the reader, it won't return. Dec 3, 2015 at 0:52
• Right, but this is code-golf. It's not a big deal if people have to type Control-D after their input. Dec 3, 2015 at 1:50

# Candy, 298348 392 bytes

Although Candy is stack based, I'm not sure that really helped...

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


Formatted a bit reveals a bit of structure:

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


The actual math occurs on the last two lines. It's driven there by a jump table on the third line.

• Dang, I see that I missed DivisionByZero, NegativeFactorial, and Overflow. I was just looking at the test cases! Dec 4, 2015 at 12:14
• Wow, this is cool. I just might need to look up candy. Dec 4, 2015 at 14:11
• I'm still working on how exactly to define overflow. Dec 4, 2015 at 19:20
• Actually I had the same problem in my answer. See the comments below my answer. Dec 4, 2015 at 19:22
• Fixed the Overflow now. I used the same approach as the Ruby, which is just to compare to 2^64 at the end of each operation. Dec 4, 2015 at 20:08