-1

I would like to understand a code that creates a RPN calculator:

class RPNCalculator
  def evaluate(expression)
    operators = ["+", "-", "*"]
    stack = []
    array = expression.split(" ")
    array.each do |i|
      if operators.include?(i)
        second_operand = stack.pop
        first_operand = stack.pop
        stack.push(first_operand.send(i, second_operand))
      else
        stack.push(i.to_i)
      end
    end
    stack.pop
  end
end

I do not understand these lines in particular:

if operators.include?(i)
  second_operand = stack.pop
  first_operand = stack.pop
  stack.push(first_operand.send(i, second_operand))
else
  stack.push(i.to_i)

If someone could give me a full run down of the code, it would be very helpful.

sawa
  • 165,429
  • 45
  • 277
  • 381
bamboopanda
  • 61
  • 1
  • 1
  • 6

2 Answers2

1

stack is a place to keep the intermediate state of the calculation. Initially, it is an empty array. During the calculation, it should be filled with integers, and at the end, it should be filled with a single integer, which is the result of the calculation.

if operators.include?(i) checks if the next element i is within the list of operators ["+", "-", "*"]. If it is, then

second_operand = stack.pop
first_operand = stack.pop

removes the last two elements in the stack, and

first_operand.send(i, second_operand)

calculates the value with i being the operator and the two elements being the operands. Then

stack.push(...)

puts back the calculated value. Otherwise,

stack.push(i.to_i)

converts the element (string) into an integer, and appends to the stack.

sawa
  • 165,429
  • 45
  • 277
  • 381
0

I'm not great in Ruby myself but some of this applies to other languages as well so I'll give it a shot.

So by the time you get to the block you mentioned, array contains the equation and stack is empty. Let's say the expression is 2 5 * 1 +, so array is equal to ["2", "5", "*", "1", "+"].

The .each block will iterate through array. First we check to see if the item is an operator (in the operators array). Initially, it isn't (it's 2) so we just convert it to a number and push that to the stack. So now stack is [2]. Same thing with the next iteration, it isn't an operator, so now stack is [2, 5].

The next item in the array is "*", which does exist in the operators array. So let's set to vars: we pop the first item off of stack and set second_operand (that is the 5) and pop another into first_operand (the 2) and calculate the result. That's where send comes in. That result, 10, now goes into stack (which now is [10].

Another number, so stack is now [10, 1]. Then the "+". So once again, pop the 10, pop the 1, and do the addition, and push back into stack: [11].

We're all done, so pop the 11 out of stack and return that value.

Community
  • 1
  • 1
mherzig
  • 1,528
  • 14
  • 26