Skip to content

Commit 7bbdae5

Browse files
authored
Enhance docs, add more tests in RomanToInteger (#5926)
1 parent aaaf96b commit 7bbdae5

File tree

2 files changed

+73
-31
lines changed

2 files changed

+73
-31
lines changed

src/main/java/com/thealgorithms/conversions/RomanToInteger.java

+56-29
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,27 @@
33
import java.util.HashMap;
44
import java.util.Map;
55

6+
/**
7+
* A utility class to convert Roman numerals into integers.
8+
*
9+
* <p>Roman numerals are based on seven symbols given below:
10+
* <ul>
11+
* <li>I = 1</li>
12+
* <li>V = 5</li>
13+
* <li>X = 10</li>
14+
* <li>L = 50</li>
15+
* <li>C = 100</li>
16+
* <li>D = 500</li>
17+
* <li>M = 1000</li>
18+
* </ul>
19+
*
20+
* <p>If a smaller numeral appears before a larger numeral, it is subtracted.
21+
* Otherwise, it is added. For example:
22+
* <pre>
23+
* MCMXCIV = 1000 + (1000 - 100) + (100 - 10) + (5 - 1) = 1994
24+
* </pre>
25+
*/
626
public final class RomanToInteger {
7-
private RomanToInteger() {
8-
}
927

1028
private static final Map<Character, Integer> ROMAN_TO_INT = new HashMap<>() {
1129
{
@@ -19,44 +37,53 @@ private RomanToInteger() {
1937
}
2038
};
2139

40+
private RomanToInteger() {
41+
}
42+
43+
/**
44+
* Converts a single Roman numeral character to its integer value.
45+
*
46+
* @param symbol the Roman numeral character
47+
* @return the corresponding integer value
48+
* @throws IllegalArgumentException if the symbol is not a valid Roman numeral
49+
*/
2250
private static int romanSymbolToInt(final char symbol) {
2351
return ROMAN_TO_INT.computeIfAbsent(symbol, c -> { throw new IllegalArgumentException("Unknown Roman symbol: " + c); });
2452
}
2553

26-
// Roman Number = Roman Numerals
27-
2854
/**
29-
* This function convert Roman number into Integer
55+
* Converts a Roman numeral string to its integer equivalent.
56+
* Steps:
57+
* <ol>
58+
* <li>Iterate over the string from right to left.</li>
59+
* <li>For each character, convert it to an integer value.</li>
60+
* <li>If the current value is greater than or equal to the max previous value, add it.</li>
61+
* <li>Otherwise, subtract it from the sum.</li>
62+
* <li>Update the max previous value.</li>
63+
* <li>Return the sum.</li>
64+
* </ol>
3065
*
31-
* @param a Roman number string
32-
* @return integer
66+
* @param roman the Roman numeral string
67+
* @return the integer value of the Roman numeral
68+
* @throws IllegalArgumentException if the input contains invalid Roman characters
69+
* @throws NullPointerException if the input is {@code null}
3370
*/
34-
public static int romanToInt(String a) {
35-
a = a.toUpperCase();
36-
char prev = ' ';
71+
public static int romanToInt(String roman) {
72+
if (roman == null) {
73+
throw new NullPointerException("Input cannot be null");
74+
}
3775

76+
roman = roman.toUpperCase();
3877
int sum = 0;
39-
40-
int newPrev = 0;
41-
for (int i = a.length() - 1; i >= 0; i--) {
42-
char c = a.charAt(i);
43-
44-
if (prev != ' ') {
45-
// checking current Number greater than previous or not
46-
newPrev = romanSymbolToInt(prev) > newPrev ? romanSymbolToInt(prev) : newPrev;
47-
}
48-
49-
int currentNum = romanSymbolToInt(c);
50-
51-
// if current number greater than prev max previous then add
52-
if (currentNum >= newPrev) {
53-
sum += currentNum;
78+
int maxPrevValue = 0;
79+
for (int i = roman.length() - 1; i >= 0; i--) {
80+
int currentValue = romanSymbolToInt(roman.charAt(i));
81+
if (currentValue >= maxPrevValue) {
82+
sum += currentValue;
83+
maxPrevValue = currentValue;
5484
} else {
55-
// subtract upcoming number until upcoming number not greater than prev max
56-
sum -= currentNum;
85+
sum -= currentValue;
5786
}
58-
59-
prev = c;
6087
}
6188

6289
return sum;

src/test/java/com/thealgorithms/conversions/RomanToIntegerTest.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,31 @@
88
public class RomanToIntegerTest {
99

1010
@Test
11-
public void testRomanToInteger() {
11+
public void testValidRomanToInteger() {
1212
assertEquals(1994, RomanToInteger.romanToInt("MCMXCIV"));
1313
assertEquals(58, RomanToInteger.romanToInt("LVIII"));
1414
assertEquals(1804, RomanToInteger.romanToInt("MDCCCIV"));
15+
assertEquals(9, RomanToInteger.romanToInt("IX"));
16+
assertEquals(4, RomanToInteger.romanToInt("IV"));
17+
assertEquals(3000, RomanToInteger.romanToInt("MMM"));
1518
}
1619

1720
@Test
18-
void testRomanToIntegerThrows() {
21+
public void testLowercaseInput() {
22+
assertEquals(1994, RomanToInteger.romanToInt("mcmxciv"));
23+
assertEquals(58, RomanToInteger.romanToInt("lviii"));
24+
}
25+
26+
@Test
27+
public void testInvalidRomanNumerals() {
1928
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("Z"));
2029
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MZI"));
2130
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MMMO"));
2231
}
32+
33+
@Test
34+
public void testEmptyAndNullInput() {
35+
assertEquals(0, RomanToInteger.romanToInt("")); // Empty string case
36+
assertThrows(NullPointerException.class, () -> RomanToInteger.romanToInt(null)); // Null input case
37+
}
2338
}

0 commit comments

Comments
 (0)