Skip to content

Instantly share code, notes, and snippets.

@nas
Forked from jimweirich/analysis.rb
Created July 20, 2011 17:40
Show Gist options
  • Save nas/1095460 to your computer and use it in GitHub Desktop.
Save nas/1095460 to your computer and use it in GitHub Desktop.
Results from Roman Numeral Calculator Kata at @cincinnatirb
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
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