Skip to content

Instantly share code, notes, and snippets.

@moserrya
Last active December 14, 2015 18:39
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 moserrya/5130984 to your computer and use it in GitHub Desktop.
Save moserrya/5130984 to your computer and use it in GitHub Desktop.
Stabby RPN
class RPNCalculator
def initialize
@special_cases = [->(op, arr) {arr.include?('0') && op == '*' && '0'},
->(op, arr) {arr.first == ('0') && op == '/' && '0'},
->(op, arr) {arr.include?('1') && op == '*' && (arr-['1']).first},
->(op, arr) {arr.include?('0') && op =~ /[+-]/ && (arr-['0']).first}]
end
def evaluate(*inputs)
symbol_to_value = inputs[1..-1].last || {}
@stack = []
inputs.first.split.each do |element|
element = (symbol_to_value[element.to_sym] || element).to_s
if element =~ /[+-\/*]/
special_case = @special_cases.find {|spc| spc.call element, @stack[-2..-1]}
if special_case
@stack[-1] = special_case.call element, [@stack[-2], @stack.pop]
else
two_numbers_on_stack? ? compute(element) : @stack << element
end
else
@stack << element
end
end
@stack.join(' ')
end
def two_numbers_on_stack?
@stack[-1] =~ /\d+/ && @stack[-2] =~ /\d+/
end
def compute(element)
@stack[-1] = eval("#{@stack[-2]} #{element} #{@stack.pop}").to_s
end
end
calc = RPNCalculator.new
puts calc.evaluate('3 4 +') == '7'
puts calc.evaluate('y x +') == 'y x +'
puts calc.evaluate('3 1 x * +') == '3 x +'
puts calc.evaluate('0 x +') == 'x'
puts calc.evaluate('x y +', :x => 1, :y => 2) == '3'
puts calc.evaluate('x y +', :x => 1) == '1 y +'
puts calc.evaluate('x y +', :y => 10) == 'x 10 +'
puts calc.evaluate('w z *', :z => 1) == 'w'
puts calc.evaluate('z x y + *', :z => 10) == '10 x y + *'
puts calc.evaluate('z x y + *', :x => 1, :y => 2) == 'z 3 *'
puts calc.evaluate('z x y + *', :z => 10, :x => 3) == '10 3 y + *'
p calc.evaluate('b 8 5 a * * *')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment