Implementing a Reverse Polish Notation Calculator in Ruby
A couple weeks ago I had a go at implementing an RPN calculator in Ruby. I knew I wanted the calculator to function by popping operands out of an array populated with the values of the input expression, operating upon the operands with the appropriate operator, and pushing the result back into the stack of operands.
I was able to implement this in version 1, but it took forever and the resulting code was not very beautiful. Why?
I started coding before I had a thorough understanding of RPN
20 10 5 4 + * - is what now?
I also jumped into coding before doing research on potentially relevant public methods
Oh hey there,
#eval. Guess I can delete all those instance methods I created for each operator ...
Also, I am a noob.
class RPNCalculator # Define methods for addition, multiplication, and subtraction def sum(array) result = 0 array.each do |i| result += i.to_i end result end def product(array) result = 1 array.each do |i| result *= i.to_i end result end def difference(array) if array.length < 2 0 else array.to_i - array.to_i end end # Define a method which evaluates an expression in RPN def evaluate(expression) expression_array = expression.split operands =  if expression_array.length == 1 evaluation = expression_array end expression_array.each do |i| if i.match(/[0-9]/) != nil operands.push(i) elsif i == "+" operands.push(sum(operands.pop(2))) elsif i == "*" operands.push(product(operands.pop(2))) elsif i == "-" operands.push(difference(operands.pop(2))) end end puts operands end end
When I wrote version 2 of the calculator, I had two goals: To make it shorter and more elegant, and to augment its functionality by including division and exponentiation.
class RPNCalculator def evaluate(expression) expression = expression.split operands =  evaluation =  expression.each do |x| case x when /\d/ evaluation.push(x.to_f) when "-", "/", "*", "+", "**" operands = evaluation.pop(2) evaluation.push(operands.send(x, operands)) end end puts evaluation end end