Last active
February 6, 2017 21:37
-
-
Save josepdecid/64e65361174e5efb537ecd72b120e642 to your computer and use it in GitHub Desktop.
RPN Calculator kata solution (Ruby)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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