Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@dergachev
Last active December 31, 2015 02:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dergachev/7923528 to your computer and use it in GitHub Desktop.
Save dergachev/7923528 to your computer and use it in GitHub Desktop.
Roman numeral conversion. Took about 25 minutes, with tests!
def to_roman(i)
if i > 999 or i < 1
raise "Input not supported"
end
i_ones = i % 10
i_tens = (i % 100)/10
i_hundreds = i/100
return HUNDREDS[i_hundreds] + TENS[i_tens] + ONES[i_ones]
end
def to_arabic(i)
if i.match /[^ivxlcdm]+$/ # TODO : better check
raise "Input not supported: #{i} contains invalid characters"
end
if !matches = i.scan(/^([mdc]*)?([xlc]*)([ivx]*)$/).first
raise "Input not supported: #{i} is out of range"
end
i_hundreds, i_tens, i_ones = matches
return 100 * HUNDREDS.index(i_hundreds) + 10 * TENS.index(i_tens) + ONES.index(i_ones)
end
ONES = [""] + %w{i ii iii iv v vi vii viii ix}
TENS = [""] + %w{x xx xxx xl l lx lxx lxxx xc}
HUNDREDS = [""] + %w{c cc ccc cd d dc dcc dccc cm}
TESTS = %w{8 viii 33 xxxiii 545 dxlv 1 i 49 xlix 929 cmxxix}
Hash[*TESTS].each do |k,v|
k = k.to_i
if to_roman(k) != v
puts "FAILURE: to_roman(#{k}) should be #{v}, got #{to_roman(k)}"
end
if to_arabic(v) != k
puts "FAILURE: to_arabic(#{v}) should be #{k}, got #{to_arabic(v)}"
end
end
# Was this useful? YES! It caught a type which caused to_roman(700) => cc.
(1..999).select{|i| i != to_arabic(to_roman(i)) }.each do |i|
puts "FAILURE: to_arabic(to_roman(#{i})) is #{to_arabic(to_roman(i))}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment