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