Created
April 3, 2015 14:52
-
-
Save ooesili/f7da3d1a270758db99d8 to your computer and use it in GitHub Desktop.
Roman Numerals
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
#!/usr/bin/env ruby | |
########## GRAB AND VALIDATE INPUT ########## | |
num_str = STDIN.gets.chomp | |
if not (1..4999).include? num_str.to_i | |
warn "number must be between 1 and 4999 (inclusive)" | |
exit 1 | |
end | |
########## PAIR UP DIGITS WITH NUMERALS ########## | |
# digits from the input, as numbers, lowest value first | |
digits = num_str.each_char.map(&:to_i).reverse | |
# each digit can be resolved independantly, given the ones, fives, and tens | |
# numerals for that digit's place | |
numerals = [ | |
['I', 'V', 'X'], | |
['X', 'L', 'C'], | |
['C', 'D', 'M'], | |
['M', '', ''] | |
] | |
########## MAIN ALGORITHM ########## | |
# pair each digit with the numerals need to resolve it | |
result = digits.zip(numerals).reduce('') do |result, (digit, (one, five, ten))| | |
# 0..4 is nothing, 4..8 is the fives numeral, 9 is the tens numeral | |
bases = ['', five, ten] | |
base = bases[(digit+1) / 5] | |
# avoid adding nil to strings | |
# pre and post will both be blank if mod_five is 0 | |
pre = post = '' | |
# we use `digit % 5` in a few places, so let's calculate it once | |
mod_five = digit % 5 | |
if mod_five == 4 | |
# prepend a ones numeral for 4 and 9 | |
pre = one | |
elsif mod_five > 0 or one == 'M' | |
# this will match 1..3, or anything if we're on the thousands place | |
# we need this special case to get 'MMMM' | |
post = one * mod_five | |
end | |
# prepend to the result since this loop starts with the lowest value first | |
pre + base + post + result | |
end | |
########## PRINT THE RESULT ########## | |
puts result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment