-
-
Save nas/1095460 to your computer and use it in GitHub Desktop.
Results from Roman Numeral Calculator Kata at @cincinnatirb
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 RomanNumeralCalculator | |
def calculate(numeral) | |
if numeral =~ /^\d+$/ | |
arabic_to_roman(numeral) | |
else | |
roman_to_arabic(numeral) | |
end | |
end | |
private | |
ROMAN_REDUCTIONS = [ | |
["M", 1000], | |
["CM", 900], | |
["D", 500], | |
["CD", 400], | |
["C", 100], | |
["XC", 90], | |
["L", 50], | |
["XL", 40], | |
["X", 10], | |
["IX", 9], | |
["V", 5], | |
["IV", 4], | |
["I", 1]] | |
ROMAN_VALUES = Hash[*ROMAN_REDUCTIONS.flatten] | |
def arabic_to_roman(numeral) | |
n = numeral.to_i | |
result = "" | |
ROMAN_REDUCTIONS.each do |roman_digit, val| | |
while n >= val | |
result << roman_digit | |
n -= val | |
end | |
end | |
result | |
end | |
def roman_to_arabic(numeral) | |
result = 0 | |
numerals = numeral.split(//) | |
while !numerals.empty? | |
a, b = numerals | |
if value_of(a) >= value_of(b) | |
result += value_of(a) | |
else | |
result += value_of(b) - value_of(a) | |
numerals.shift | |
end | |
numerals.shift | |
end | |
result.to_s | |
end | |
def value_of(roman_digit) | |
ROMAN_VALUES[roman_digit] || 0 | |
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 'rspec/given' | |
require 'roman_numeral_calculator' | |
describe RomanNumeralCalculator do | |
Given(:calculator) { RomanNumeralCalculator.new } | |
def calculate(n) | |
calculator.calculate(n) | |
end | |
describe "converting Roman to Arabic" do | |
describe "with single digits" do | |
Then { calculate("I").should == "1" } | |
Then { calculate("V").should == "5" } | |
Then { calculate("X").should == "10" } | |
Then { calculate("L").should == "50" } | |
Then { calculate("C").should == "100" } | |
Then { calculate("D").should == "500" } | |
Then { calculate("M").should == "1000" } | |
end | |
describe "with multiple digits" do | |
Then { calculate("II").should == "2" } | |
Then { calculate("VIII").should == "8" } | |
Then { calculate("MMMCCCXXXIII").should == "3333" } | |
end | |
describe "with inverted ordered digits" do | |
Then { calculate("IV").should == "4" } | |
Then { calculate("IX").should == "9" } | |
Then { calculate("XL").should == "40" } | |
Then { calculate("XC").should == "90" } | |
Then { calculate("CD").should == "400" } | |
Then { calculate("CM").should == "900" } | |
end | |
describe "with the largest number" do | |
Then { calculate("MMMCMXCIX").should == "3999" } | |
end | |
end | |
describe "converting arabic to roman" do | |
Then { calculate("1").should == "I" } | |
Then { calculate("2").should == "II" } | |
Then { calculate("3").should == "III" } | |
Then { calculate("4").should == "IV" } | |
Then { calculate("5").should == "V" } | |
Then { calculate("6").should == "VI" } | |
Then { calculate("9").should == "IX" } | |
Then { calculate("10").should == "X" } | |
Then { calculate("30").should == "XXX" } | |
Then { calculate("40").should == "XL" } | |
Then { calculate("50").should == "L" } | |
Then { calculate("90").should == "XC" } | |
Then { calculate("100").should == "C" } | |
Then { calculate("400").should == "CD" } | |
Then { calculate("900").should == "CM" } | |
Then { calculate("1000").should == "M" } | |
Then { calculate("3999").should == "MMMCMXCIX" } | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment