At the office today we did a coding dojo and the kata that we used was Roman Numerals. We actually did the kata in Java because that was what everyone was familiar with but I decided to work on doing it in Ruby.

After after 20 minutes I got a working solution. However, that's when the fun starts! I spent some time trying several refactorings on the code and didn't really get anywhere. The code that I was refactoring looked roughly like this

```@value_map = {
1 => "I",
4 => "IV",
5 => "V",
9 => "IX",
10 => "X",
...
}

[..., 10, 9, 5, 4, 1].each do |value|
while(number >= value)
number -= value
result += @value_map[value]
end
end
```

Because of the expressiveness of Ruby, this code is terse. However, we are covering our edge cases in an odd way. This worked and I couldn't necessarily refactor it to be better. However, I knew that if we added a feature that those edge cases would make it start to look ugly. So, I added a feature (and learned something about roman numerals!). Instead of just going to 3999, we would support 38,999. This meant we needed to add the roman numerals (V) = 5,000 and (X) = 10,000. I added the feature and then refactored and ended up with something like this

```class Romans
def initialize
@value_map = {
1 => "I",
5 => "V",
10 => "X",
50 => "L",
100 => "C",
500 => "D",
1000 => "M",
5000 => "(V)",
10000 => "(X)",
}
end

def convert integer
result = ""
[10_000, 1000, 100, 10, 1].each do |value|
integer, result = convert_to_highest_significant_digit integer, value, result
end
result
end

def convert_to_highest_significant_digit integer, value, result
if integer >= value * 9
result += @value_map[value] + @value_map[value * 10]
integer -= value * 9
elsif integer >= value * 5
result += @value_map[value * 5]
integer -= value * 5
elsif integer >= value * 4
result += @value_map[value] + @value_map[value * 5]
integer -= value * 4
end

while integer >= value
result += @value_map[value]
integer -= value
end

[integer, result]
end
end
```

The code above is not without problems, either. We have to lean on the Ruby feature of multiple returns. We also have that ugly if/elsif/elsif statement. We may be able to handle this with another object, though. Here is a more object oriented way

```class Romans
def initialize
@values = [
RomanDigitGroup.new(
RomanDigit.new(1, "I"),
RomanDigit.new(5, "V"),
RomanDigit.new(10, "X")
),
RomanDigitGroup.new(
RomanDigit.new(10, "X"),
RomanDigit.new(50, "L"),
RomanDigit.new(100, "C")
),
RomanDigitGroup.new(
RomanDigit.new(100, "C"),
RomanDigit.new(500, "D"),
RomanDigit.new(1000, "M")
),
RomanDigitGroup.new(
RomanDigit.new(1000, "M"),
RomanDigit.new(5000, "(V)"),
RomanDigit.new(10_000, "(X)")
),
]
end

def convert integer
result = ""
@values.reverse.each do |value|
roman = value.convert_to_roman(integer)
integer -= value.max_represented_value(integer)
result += roman
end
result
end
end

class RomanDigit

def initialize value, roman
@value = value
@roman = roman
end
end

class RomanDigitGroup

def initialize one, five, ten
@one = one
@five = five
@ten = ten
@base_value = one.value
end

def convert_to_roman integer
result = ""

while integer >= ten_x
result += @ten.roman
integer -= ten_x
end

if integer >= nine_x
result += @one.roman + @ten.roman
integer -= nine_x
elsif integer >= five_x
result += @five.roman
integer -= five_x
elsif integer >= four_x
result += @one.roman + @five.roman
integer -= four_x
end

while integer >= one_x
result += @one.roman
integer -= one_x
end

result
end

def max_represented_value integer
integer_start = integer

integer -= ten_x while integer >= ten_x

if integer >= nine_x
integer -= nine_x
elsif integer >= five_x
integer -= five_x
elsif integer >= four_x
integer -= four_x
end

integer -= one_x while integer >= one_x

integer_start - integer
end

private

def ten_x
@base_value * 10
end

def nine_x
@base_value * 9
end

def five_x
@base_value * 5
end

def four_x
@base_value * 4
end

def one_x
@base_value
end
end
```

Unfortunately, that doesn't look exactly right either. We still have the complexity of the while and if/elsifs. The object oriented form may be easier to read and understand but I think it is a little heavy for our purposes (the RomanDigitGroup class conveys how Roman Numerals actually work). This method also allows us to get rid of the hash data structure and the duplication of data (hash and array in the prior implementations).

So, where do I go from here? I'm not really sure. Is there a clever trick to get rid of the ugly while and if statements? Is there a better abstraction that could be applied? Maybe this algorithm has irreducible complexity? I personally like the second version (non object oriented with ugly if statements) best.