Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
Let's consider a simple solution to the problem of converting a Roman numeral to a decimal (Ruby).
Condition
Create a function solution that takes a string — a Roman numeral — and returns its value as a decimal integer.
No validation of the correctness of the Roman notation is needed.
Examples:
- "MCMXC" → 1990
- "MMVIII" → 2008
- "MDCLXVI" → 1666
How does the conversion of Roman numerals to decimals work?
Roman numerals are a numeral system based on symbols, each corresponding to a specific value: I — 1, V — 5, X — 10, L — 50, C — 100, D — 500, M — 1000. To write a number, the symbols are combined according to certain rules. If a symbol of lesser value stands before a greater one (for example, IV), it means subtraction (5 - 1 = 4). If the opposite is true, they are added (VI = 5 + 1 = 6). This logic allows for compact representation of both simple and complex numbers, such as MCMXC for 1990.
When converting Roman numerals to decimals, the computer algorithm processes the string's characters from right to left. This makes it easy to determine whether to add or subtract the value of the symbol. For example, in XIV, processing starts with V = 5, then I = 1 (less than V, so we subtract: 5 - 1 = 4), then X = 10 (greater than I, so we add: 10 + 4 = 14). This approach allows for efficient implementation of the conversion even in a few lines of code.
Test (rspec) to check the method
RSpec.describe '#solution' do
it 'converts simple Roman numerals' do
expect(solution('I')).to eq(1)
expect(solution('III')).to eq(3)
expect(solution('VIII')).to eq(8)
end
it 'converts compound Roman numerals' do
expect(solution('IV')).to eq(4)
expect(solution('IX')).to eq(9)
expect(solution('XL')).to eq(40)
expect(solution('XC')).to eq(90)
end
it 'converts large Roman numerals' do
expect(solution('MCMXC')).to eq(1990)
expect(solution('MMVIII')).to eq(2008)
expect(solution('MDCLXVI')).to eq(1666)
expect(solution('MMMCMXCIX')).to eq(3999)
end
end
Method solution
One of the solutions (using Ruby, the same things can be done in many ways).
def solution(roman)
values = {
'M' => 1000,
'D' => 500,
'C' => 100,
'L' => 50,
'X' => 10,
'V' => 5,
'I' => 1
}
total = 0
prev = 0
roman.chars.reverse.each do |char|
current = values[char]
if current < prev
total -= current
else
total += current
prev = current
end
end
total
end
How the algorithm works
We move from the end of the string, adding the values of the symbols. If the current number is less than the previous one — we subtract it, otherwise — we add it. This allows for correct handling of cases like IV or CM.
This post doesn't have any additions from the author yet.