In an effort to continue learning Ruby, I thought it would be fun to write a simple, reverse Polish notation (RPN) calculator.
In RPN, the operator follows the operands. An RPN expression is easy to evaluate. We scan the expression from left to right. When we see an operand, we push the operand to a stack. When we see an operator, we pop two operands from the stack, apply the operator to these pop'd values, and push the result value back on the stack. When we reach the end of the expression, the stack should have only one element, which is the result of the expression.
rpnc.rb
#!/usr/bin/env ruby
def compute(op, a, b)
case op
when '+'
a + b
when '-'
a - b
when '*'
a * b
when '/'
a / b
else
raise ArgumentError.new("undefined op #{op}")
end
end
def is_operand?(s)
s =~ /^[-+]?[0-9]+$/
end
def is_operator?(s)
ops = ['+', '-', '*', '/']
ops.include?(s)
end
def evaluate(tokens)
line = tokens.join(' ')
operands = []
tokens.each do |token|
if is_operand?(token)
operands << token.to_i
elsif is_operator?(token)
if operands.length < 2
raise "bad expression '#{line}'"
end
operands << compute(token, operands.pop, operands.pop)
else
raise "bad token '#{token}'"
end
end
if operands.length != 1
raise "bad expression '#{line}'"
end
operands[0]
end
def parse
line = gets.chomp
tokens = line.split
end
def main
tokens = parse
puts evaluate(tokens)
end
main
example
$ ./rpnc 10 2 + 6 - 4 * -24
No comments:
Post a Comment