Roman Numerals Converter Explained
I’m going to spend this post explaining a roman numeral converter I made for one of our morning todo assignments. I struggled with this assignment, so I thought the best way to really drive it home would be to explain it.
First, within the Integer
class, I defined as a constant variable a hash of that is representative of all of the roman numeral characters within their counting system. I cheated a little bit and included instances of 4 and 9, because those are a bit complicated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
The instance of the Integer
class method is a number, which I called in the initialize method.
1 2 3 |
|
Once I got that out of the way, I began to think about the logic of the roman numerals. Generally, it’s addition and substraction. The number 40, for example is representated as XL. L is 50 and X is 10. 50(L) – 10(X) is 40. Or, the number 13 is XIIII. 10(X) + 1(I) +1(I) +1(I) is 11. The relationship is one of addition and subtraction when you are trying to represent a number that is not a singular character within the roman numeral library.
How to execute this relationship through code is the complicated part. I am at that point in my learning where I know what I want to accomplish with code, but the execution doesn’t come completely naturally. If I compare it to language learning, I am in the recognition stage and still somewhat fumbling with the recollection.
I executed this converter with two methods. The first method, lower_key
, takes an instance number as an argument, and returns the largest number below it which has an associated roman numeral. to_roman
uses the return of lower_key
to help generate the roman numeral associated with the instance of number
. I’ll discuss lower_key
first.
First, I create a new array, numbers_array
, and I .collect
all of the numbers in my NUMERALS
hash and sort them:
1
|
|
This gives me an easy array of the numbers to work with when I compare them to number
.
Before I mentioned that the logic of roman numerals is that we’re adding roman numeral characters together to make a number. In order to do that, we need to know the number right below it to work on that. To do this, I iterated over my new numbers_array
with .each_with_index
. In numbers_array
the number (I called it decimal
) below number
can be found through first determining the number above it. Then, using its index
, I can access the number below. Then, returning the .last
in numbers_array
accounts for if number
is greater than the largest number in NUMERALS
, like 3000.
1 2 3 4 5 6 |
|
Onto the to_roman
method. First, I confirmed that number
is self
. I then set a variable roman_numeral = ""
; I will be pushing into this string below.
The bulk of the method in enclosed in a while
loop. If NUMERALS
includes number
, set that NUMERALS[number]
as roman_numeral
. This takes care of instances of number
that are simple and already defined in NUMERALS
, like 5(V). For more complicated instances, we loop beyond this.
Let’s take a more complicated number like 51(LI) as an example to follow through. It doesn’t apply yet to the if
block, but instead is passed into the else
first. lower_key(51)
is called, which returns 50. “L” is added into roman_numeral
(roman_numeral += NUMERALS[50]
). Then the remainder of that (number -= 50
) is 1, which is passed up and looped through. NUMERALS
has that as a key, where the value is “I”, and that is pushed into roman_numeral
, right behind the “L” already in there from before. “LI” is returned.
1 2 3 4 5 6 7 8 9 |
|
Below is the entire program.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|