Skip to content

Instantly share code, notes, and snippets.

@alainravet
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alainravet/03a42ed33581beb9be43 to your computer and use it in GitHub Desktop.
Save alainravet/03a42ed33581beb9be43 to your computer and use it in GitHub Desktop.
a RPN calculator in 19 lines of Ruby
def RPN(*data)
stack = []
data.each do |el|
case el
when :+, :-, :*, :/, :&, :|, :<< # 1,2,3,:*,:+ == 1 + 2 $ 3
a, b = stack.pop(2)
stack.push a.send(el.to_sym, b)
when Class # 3,Float == Float(3)
stack.push send(el.name, stack.pop)
when Symbol # '1+2',:eval == eval('1+2')
stack.push send(el, stack.pop)
when Proc # 3,->(n){2*n} == ->(n){2*n}.call(3)
stack.push el.(*stack.pop(el.arity))
else
stack << el
end
end
stack.pop
end
# Tests :
def assert_eq(l,r)
l==r or fail "#{l} != #{r}"
end
assert_eq "AZ", RPN("A", "Z", ->(a, b){a+b} )
assert_eq 3, RPN('1+2', :eval)
assert_eq 15, RPN(5, ->(v){3*v})
assert_eq (Float(3) / 2), RPN(3, Float, 2, :/)
assert_eq (1+2*3), RPN(1, 2, 3, :*, :+)
assert_eq (1+2), RPN(1, 2, :+)
assert_eq (16<<2), RPN(16, 2, :<<)
assert_eq 'ab', RPN('a', 'b', :+)
assert_eq (10/2), RPN(10, 2, :/)
assert_eq (3-2), RPN(3, 2, :-)
assert_eq (3*2), RPN(3, 2, :*)
assert_eq false, RPN(true, false, :&)
assert_eq true, RPN(true, false, :|)
# assert_eq false, RPN(true, false, :'&&') !!does not work
# assert_eq true, RPN(true, false, :'||') !!does not work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment