Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Converting Roman Numerals to Integers: Implementation and Comparison

Tools 1

Roman numerals utilize seven specific symbols: I, V, X, L, C, D, and M. Their corresponding values are:

Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

Numbers are formed by combining these symbols, typically written from largest to smallest value from left to right. For instance, "XII" represents X + II, equaling 12.

However, a subtractive principle applies in six specific cases to avoid repeating a symbol four times:

  • I placed before V (5) or X (10) makes 4 (IV) and 9 (IX).
  • X placed before L (50) or C (100) makes 40 (XL) and 90 (XC).
  • C placed before D (500) or M (1000) makes 400 (CD) and 900 (CM).

The objective is to convert a given Roman numeral string to its integer equivaelnt.

Test Cases

  • Input: "III" → Output: 3
  • Input: "IV" → Output: 4
  • Input: "IX" → Output: 9
  • Input: "LVIII" → Output: 58 (L=50, V=5, III=3)
  • Input: "MCMXCIV" → Output: 1994 (M=1000, CM=900, XC=90, IV=4)

Solution Approaches

Approach 1: Look-Ahead Substring Mapping

This method iterates through the string, examining potential two-character combinations first. A dictionary stores all fundamental symbols and the six special compound numerals. For each position i, if i+1 is within bounds, a two-character substring is formed. If this substring exists in the dictionary, its value is added to the total and the index advances by 2. Otherwise, the single character at i is mapped and added, advancing the index by 1.

Java Implemantation

import java.util.HashMap;

class RomanNumeralDecoder {
    public int convert(String romanStr) {
        HashMap<String, Integer> valueMap = new HashMap<>() {{
            put("I", 1);
            put("V", 5);
            put("X", 10);
            put("L", 50);
            put("C", 100);
            put("D", 500);
            put("M", 1000);
            put("IV", 4);
            put("IX", 9);
            put("XL", 40);
            put("XC", 90);
            put("CD", 400);
            put("CM", 900);
        }};
        int idx = 0;
        int total = 0;
        while (idx < romanStr.length()) {
            if (idx + 1 < romanStr.length()) {
                String dualChar = romanStr.substring(idx, idx + 2);
                if (valueMap.containsKey(dualChar)) {
                    total += valueMap.get(dualChar);
                    idx += 2;
                    continue;
                }
            }
            total += valueMap.get(romanStr.substring(idx, idx + 1));
            idx++;
        }
        return total;
    }
}

Approach 2: Sequential Value Comparison

This method leverages the rule that subtractive notation (e.g., IV) occurs when a smaller value precedes a larger one. The algorithm sequentially processes each symbol. It maintains the value of the previous symbol. For the current symbol's value:

  • If the currrent value is greater than the previous value, it indicates a subtractive pair (like IV). Therefore, the previous value is subtracted from the running total.
  • If the current value is less than or equal to the previous value, the previous value is added to the total (as it belongs to a normal descending sequence). Finally, the last symbol's value is added to the total after the loop.

Java Implementation

class RomanNumeralConverter {
    public int romanToInteger(String romanStr) {
        int result = 0;
        int priorVal = mapCharToValue(romanStr.charAt(0));
        for (int pos = 1; pos < romanStr.length(); pos++) {
            int currentVal = mapCharToValue(romanStr.charAt(pos));
            if (currentVal > priorVal) {
                result -= priorVal;
            } else {
                result += priorVal;
            }
            priorVal = currentVal;
        }
        result += priorVal;
        return result;
    }

    private int mapCharToValue(char symbol) {
        return switch (symbol) {
            case 'I' -> 1;
            case 'V' -> 5;
            case 'X' -> 10;
            case 'L' -> 50;
            case 'C' -> 100;
            case 'D' -> 500;
            case 'M' -> 1000;
            default -> 0;
        };
    }
}

Both approaches correctly handle standard and subtractive Roman numeral patterns, with the second method often being more space-efficient.

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.