diff --git a/src/main/java/com/thealgorithms/conversions/RomanToInteger.java b/src/main/java/com/thealgorithms/conversions/RomanToInteger.java index 1934e9b26..a634c7203 100644 --- a/src/main/java/com/thealgorithms/conversions/RomanToInteger.java +++ b/src/main/java/com/thealgorithms/conversions/RomanToInteger.java @@ -3,9 +3,27 @@ package com.thealgorithms.conversions; import java.util.HashMap; import java.util.Map; +/** + * A utility class to convert Roman numerals into integers. + * + *

Roman numerals are based on seven symbols given below: + *

+ * + *

If a smaller numeral appears before a larger numeral, it is subtracted. + * Otherwise, it is added. For example: + *

+ *   MCMXCIV = 1000 + (1000 - 100) + (100 - 10) + (5 - 1) = 1994
+ * 
+ */ public final class RomanToInteger { - private RomanToInteger() { - } private static final Map ROMAN_TO_INT = new HashMap<>() { { @@ -19,44 +37,53 @@ public final class RomanToInteger { } }; + private RomanToInteger() { + } + + /** + * Converts a single Roman numeral character to its integer value. + * + * @param symbol the Roman numeral character + * @return the corresponding integer value + * @throws IllegalArgumentException if the symbol is not a valid Roman numeral + */ private static int romanSymbolToInt(final char symbol) { return ROMAN_TO_INT.computeIfAbsent(symbol, c -> { throw new IllegalArgumentException("Unknown Roman symbol: " + c); }); } - // Roman Number = Roman Numerals - /** - * This function convert Roman number into Integer + * Converts a Roman numeral string to its integer equivalent. + * Steps: + *
    + *
  1. Iterate over the string from right to left.
  2. + *
  3. For each character, convert it to an integer value.
  4. + *
  5. If the current value is greater than or equal to the max previous value, add it.
  6. + *
  7. Otherwise, subtract it from the sum.
  8. + *
  9. Update the max previous value.
  10. + *
  11. Return the sum.
  12. + *
* - * @param a Roman number string - * @return integer + * @param roman the Roman numeral string + * @return the integer value of the Roman numeral + * @throws IllegalArgumentException if the input contains invalid Roman characters + * @throws NullPointerException if the input is {@code null} */ - public static int romanToInt(String a) { - a = a.toUpperCase(); - char prev = ' '; + public static int romanToInt(String roman) { + if (roman == null) { + throw new NullPointerException("Input cannot be null"); + } + roman = roman.toUpperCase(); int sum = 0; - - int newPrev = 0; - for (int i = a.length() - 1; i >= 0; i--) { - char c = a.charAt(i); - - if (prev != ' ') { - // checking current Number greater than previous or not - newPrev = romanSymbolToInt(prev) > newPrev ? romanSymbolToInt(prev) : newPrev; - } - - int currentNum = romanSymbolToInt(c); - - // if current number greater than prev max previous then add - if (currentNum >= newPrev) { - sum += currentNum; + int maxPrevValue = 0; + for (int i = roman.length() - 1; i >= 0; i--) { + int currentValue = romanSymbolToInt(roman.charAt(i)); + if (currentValue >= maxPrevValue) { + sum += currentValue; + maxPrevValue = currentValue; } else { - // subtract upcoming number until upcoming number not greater than prev max - sum -= currentNum; + sum -= currentValue; } - - prev = c; } return sum; diff --git a/src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java b/src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java index f03563971..971eff8c7 100644 --- a/src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java +++ b/src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java @@ -8,16 +8,31 @@ import org.junit.jupiter.api.Test; public class RomanToIntegerTest { @Test - public void testRomanToInteger() { + public void testValidRomanToInteger() { assertEquals(1994, RomanToInteger.romanToInt("MCMXCIV")); assertEquals(58, RomanToInteger.romanToInt("LVIII")); assertEquals(1804, RomanToInteger.romanToInt("MDCCCIV")); + assertEquals(9, RomanToInteger.romanToInt("IX")); + assertEquals(4, RomanToInteger.romanToInt("IV")); + assertEquals(3000, RomanToInteger.romanToInt("MMM")); } @Test - void testRomanToIntegerThrows() { + public void testLowercaseInput() { + assertEquals(1994, RomanToInteger.romanToInt("mcmxciv")); + assertEquals(58, RomanToInteger.romanToInt("lviii")); + } + + @Test + public void testInvalidRomanNumerals() { assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("Z")); assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MZI")); assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MMMO")); } + + @Test + public void testEmptyAndNullInput() { + assertEquals(0, RomanToInteger.romanToInt("")); // Empty string case + assertThrows(NullPointerException.class, () -> RomanToInteger.romanToInt(null)); // Null input case + } }