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:
+ *
+ * - I = 1
+ * - V = 5
+ * - X = 10
+ * - L = 50
+ * - C = 100
+ * - D = 500
+ * - M = 1000
+ *
+ *
+ * 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:
+ *
+ * - Iterate over the string from right to left.
+ * - For each character, convert it to an integer value.
+ * - If the current value is greater than or equal to the max previous value, add it.
+ * - Otherwise, subtract it from the sum.
+ * - Update the max previous value.
+ * - Return the sum.
+ *
*
- * @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
+ }
}