|
Versions Of This Snippet::
Download a raw-text version of this code by clicking on "Download Version"
Latest Snippet Version: :1.0
##########################################################
# Roman Numeral converter -- By Sam Kellett
#
# Examples:
# r = Roman.new
# r.to_int "viii" # 8
# r.to_int "mcmxcix" # 1999
# r.viii # 8
# r.mcmxcix # 1999
# r.to_roman 2550 # "mmdl"
# r.to_roman 9 # "ix"
# 2550.to_roman # "mmdl"
#
# Supports:
# Rules regarding Roman numerals often state that a symbol representing 10x may not
# precede any symbol larger than 10x+1. For example, C cannot be preceded by I or V,
# only by X (or, of course, by a symbol representing a value equal to or larger than
# C). Thus, one should represent the number "ninety-nine" as XCIX, not as the
# "shortcut" IC.
# -- Wikipedia (http://en.wikipedia.org/wiki/Roman_numerals#XCIX_or_IC.3F)
#
#
# To-do:
# - Basic arithmetic with roman numerals
# - Integration with the Time and Date objects
class Roman
VALUES = ["i", "v", "x", "l", "c", "d", "m"]
NUMERAL = {
"i" => 1,
"v" => 5,
"x" => 10,
"l" => 50,
"c" => 100,
"d" => 500,
"m" => 1000
}
SHORTCUTS = {
"cm" => "dcccc",
"ld" => "ccccl",
"xc" => "lxxxx",
"vl" => "xxxxv",
"ix" => "viiii",
"iv" => "iiii"
}
def to_int(str)
total = 0
str.downcase!
return unless str =~ /^[mcdlxvi]+$/
str.gsub! Regexp.compile(SHORTCUTS.keys.join("|")) do
SHORTCUTS[$&]
end
str.split("").each do |char|
total += NUMERAL[char]
end
total
end
def to_roman(int)
numbers = reverse_hash NUMERAL
longcuts = reverse_hash SHORTCUTS
#return "bad" unless int =~ /^[0-9]+$/
roman = ""
mknum = []
remainder = int.to_i
numbers.keys.sort.reverse.each do |num|
tmp = remainder.divmod num
mknum.push tmp[0]
remainder = tmp[1]
end
values = VALUES.reverse
mknum.each_with_index do |num, i|
roman << values[i]*num
end
roman.gsub! Regexp.compile(longcuts.keys.join("|")) do
longcuts[$&]
end
roman
end
private
def reverse_hash(hsh)
tmp = {}
hsh.each do |key, value|
tmp[value] = key
end
tmp
end
def method_missing(method_id)
to_int(method_id.id2name)
end
end
class Integer
def to_roman
r = Roman.new
r.to_roman(self)
end
end
Submit a new versionYou can submit a new version of this snippet if you have modified it and you feel it is appropriate to share with others..
|
||||||||||||||||||||||||||
