Created
December 2, 2012 11:08
-
-
Save claudioc/4188239 to your computer and use it in GitHub Desktop.
Roman <=> Integer (Ruby)
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
module RomanEmpire | |
emperor = "Claudio Cicali" | |
@numbers = { | |
:letters => [ "M", "D", "C", "L", "X", "V", "I" ], | |
:integers => [ "1000", "500", "100", "50", "10", "5", "1" ] | |
} | |
def RomanEmpire.romanFor(integer) | |
@numbers[:letters][@numbers[:integers].index(integer.to_s)] | |
end | |
def RomanEmpire.integerFor(roman) | |
@numbers[:integers][@numbers[:letters].index(roman)].to_i | |
end | |
def RomanEmpire.numbers | |
@numbers | |
end | |
class Number | |
def initialize(repr) | |
@value = { | |
:integer => repr, | |
:roman => repr | |
} | |
# The self test will be removed once we have proper tests | |
if (repr =~ /\A[+-]?\d+\Z/).nil? | |
@output_type = :integer | |
@value[:integer] = parseRoman(repr, 0) | |
if (parseInteger(@value[:integer]) != @value[:roman]) | |
raise "Duo numeri non equatur! " + (@value[:roman]) + " != " + @value[:integer] | |
end | |
else | |
@output_type = :roman | |
@value[:roman] = parseInteger(repr); | |
if (parseRoman(@value[:roman], 0).to_i != @value[:integer].to_i) | |
raise "Duo numeri non equatur! " + @value[:integer] + " != " + @value[:roman] | |
end | |
end | |
end | |
def converted | |
@value[@output_type] | |
end | |
private | |
def parseRoman(roman, acc) | |
if roman[0].nil? | |
return acc | |
end | |
d0 = RomanEmpire::integerFor(roman[0].chr) | |
d1 = roman[1].nil? ? 0 : RomanEmpire::integerFor(roman[1].chr) | |
if d1 <= d0 | |
parseRoman( roman[1..-1], acc + d0 ) | |
elsif d1 > d0 | |
parseRoman( roman[2..-1], acc + ( d1 - d0 ) ) | |
end | |
end | |
def parseInteger(integer) | |
integer = integer.to_s | |
mult = 0 | |
number = "" | |
tmp = 0 | |
while integer.length > 0 | |
partial = "" | |
digit = integer[0].to_i - 48 | |
if digit > 0 | |
mult = 10 ** (integer.length - 1) | |
tmp = digit * mult | |
# This is for "special, edge cases". | |
# Example for "4": mult is 1 and and K esists so that K - 1 = 4. In that case K is 5 so that I use R(1) + R(5) which is IV | |
# Example for "400": mult is 100 and and K esists so that K - 100 = 400. In that case K is 500 so I use R(100) + R(500) which is CD | |
RomanEmpire.numbers[:integers].each { | value | | |
if (value.to_i - tmp ) == mult | |
partial = (RomanEmpire::romanFor(mult) + RomanEmpire::romanFor(value)); | |
end | |
} | |
if (partial == "") | |
RomanEmpire.numbers[:integers].each { | value | | |
value = value.to_i | |
while (tmp - value) >= 0 | |
tmp -= value | |
partial += RomanEmpire::romanFor(value); | |
end | |
} | |
end | |
number += partial | |
end | |
integer = integer[1..-1] | |
end | |
number | |
end | |
end | |
end | |
ARGF.each_line do |entry| | |
puts RomanEmpire::Number.new(entry.chop).converted | |
end |
s/me/my/
Oh yeah, I did not any check sorry. Thanks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hm for me input file, this complains about line 84 (which assumes ASCII input). If you replace it with "integer[0].to_i" it should be more portable (and works for my test files).