Sunday, May 5, 2013

Ruby Reverse Polish Notation Calculator

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