class RPNParty::Calculator

Public Class Methods

new(calculation = '') click to toggle source
# File lib/rpn_party/calculator.rb, line 5
def initialize(calculation = '')
  @stack = []
  evaluate(calculation)
end

Public Instance Methods

evaluate(calculation) click to toggle source
# File lib/rpn_party/calculator.rb, line 20
def evaluate(calculation)
  calculation.split.map do |token|
    case token
    when /\A(?:\-)?\d+(?:\.\d+)?\z/
      @stack.push token.to_f
    when /\A\+\z/
      add
    when /\A\-\z/
      subtract
    when /\A\*\z/
      multiply
    when /\A\/\z/
      divide
    else
      raise UnrecognizedInputError,
        "Unrecognized value/operator: '#{token}'. Valid inputs are numbers (0, 1, 2.5, -3, etc.), or '+', '-', '*', '/'."
    end
  end
end
result() click to toggle source
# File lib/rpn_party/calculator.rb, line 10
def result
  if @stack.empty?
    nil
  elsif @stack.length == 1
    @stack[0]
  else
    @stack
  end
end

Private Instance Methods

add() click to toggle source
# File lib/rpn_party/calculator.rb, line 42
def add
  raise_if_insufficient_operands :addition

  first_value, second_value = @stack.pop(2)
  @stack.push(first_value + second_value)
end
divide() click to toggle source
# File lib/rpn_party/calculator.rb, line 63
def divide
  raise_if_insufficient_operands :division
  raise_if_second_value_is_zero

  first_value, second_value = @stack.pop(2)
  @stack.push(first_value / second_value)
end
multiply() click to toggle source
# File lib/rpn_party/calculator.rb, line 56
def multiply
  raise_if_insufficient_operands :multiplication

  first_value, second_value = @stack.pop(2)
  @stack.push(first_value * second_value)
end
raise_if_insufficient_operands(operation) click to toggle source
# File lib/rpn_party/calculator.rb, line 78
def raise_if_insufficient_operands(operation)
  return if @stack.length >= 2

  message = if @stack.empty?
              "Could not perform #{operation}. At least two values are required, but there are none."
            else
              "Could not perform #{operation}. At least two values are required, but there is only one: '#{@stack.first}'."
            end
  raise InsufficientOperandsError,
    message
end
raise_if_second_value_is_zero() click to toggle source
# File lib/rpn_party/calculator.rb, line 71
def raise_if_second_value_is_zero
  return unless @stack.last.zero?

  raise ZeroDivisionError,
    "Cannot divide #{@stack[-2]} by 0."
end
subtract() click to toggle source
# File lib/rpn_party/calculator.rb, line 49
def subtract
  raise_if_insufficient_operands :subtraction

  first_value, second_value = @stack.pop(2)
  @stack.push(first_value - second_value)
end