Skip to content

Instantly share code, notes, and snippets.

@josepdecid
Last active February 6, 2017 21:37
Show Gist options
  • Save josepdecid/64e65361174e5efb537ecd72b120e642 to your computer and use it in GitHub Desktop.
Save josepdecid/64e65361174e5efb537ecd72b120e642 to your computer and use it in GitHub Desktop.
RPN Calculator kata solution (Ruby)
class RPN
def initialize(operation)
@operation = operation.split(' ')
end
def calculate
stack = []
@operation.each do |value|
if is_operator?(value)
stack.push(eval_subexpression(stack, value))
elsif is_number?(value)
stack.push(value)
else
raise 'Malformed expression'
end
end
stack * ' '
end
private
def eval_subexpression(stack, value)
raise 'Malformed expression' unless stack.length >= 2
b = stack.pop
a = stack.pop
operator = value == '^' ? '**' : value
eval("#{a} #{operator} #{b}").to_s rescue raise 'Division by 0'
end
def is_number?(value)
value.to_i.to_s == value rescue false
end
def is_operator?(value)
%w(+ - * / ^).include? value
end
end
require 'minitest/autorun'
require './rpn'
class TestRPN < Minitest::Test
def test_when_empty_input_returns_empty_result
rpn = RPN.new('')
assert_equal '', rpn.calculate
end
def test_single_number_returns_same_number
rpn = RPN.new('5')
assert_equal '5', rpn.calculate
end
def test_add_two_numbers_returns_the_addition
rpn = RPN.new('5 3 +')
assert_equal '8', rpn.calculate
end
def test_with_three_operands_returns_correct_value
rpn = RPN.new('4 2 + 3 -')
assert_equal '3', rpn.calculate
end
def test_with_multiple_operands_with_priorities_returns_correct_result
rpn = RPN.new('3 5 8 * 7 + *')
assert_equal '141', rpn.calculate
end
def test_with_extra_values_without_operator_returns_appended_results
rpn = RPN.new('7 2 - 3 4')
assert_equal '5 3 4', rpn.calculate
end
def test_with_exponentiation_returns_exponent_result
rpn = RPN.new('7 2 ^')
assert_equal '49', rpn.calculate
end
def test_when_divide_by_zero_raise_custom_divison_exception
rpn = RPN.new('7 0 /')
assert_raises 'Division by 0' do
rpn.calculate
end
end
def test_when_non_valid_characters_raise_custom_malformed_expression
rpn = RPN.new('7 2 &')
assert_raises 'Malformed expression' do
rpn.calculate
end
end
def test_when_operators_placed_wrong_raise_custom_malformed_expression
rpn = RPN.new('7 2 + +')
assert_raises 'Malformed expression' do
rpn.calculate
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment