mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 01:35:16 +08:00
Enhance docs, add more tests in RomanToInteger
(#5926)
This commit is contained in:
@ -3,9 +3,27 @@ package com.thealgorithms.conversions;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class to convert Roman numerals into integers.
|
||||||
|
*
|
||||||
|
* <p>Roman numerals are based on seven symbols given below:
|
||||||
|
* <ul>
|
||||||
|
* <li>I = 1</li>
|
||||||
|
* <li>V = 5</li>
|
||||||
|
* <li>X = 10</li>
|
||||||
|
* <li>L = 50</li>
|
||||||
|
* <li>C = 100</li>
|
||||||
|
* <li>D = 500</li>
|
||||||
|
* <li>M = 1000</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>If a smaller numeral appears before a larger numeral, it is subtracted.
|
||||||
|
* Otherwise, it is added. For example:
|
||||||
|
* <pre>
|
||||||
|
* MCMXCIV = 1000 + (1000 - 100) + (100 - 10) + (5 - 1) = 1994
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public final class RomanToInteger {
|
public final class RomanToInteger {
|
||||||
private RomanToInteger() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Character, Integer> ROMAN_TO_INT = new HashMap<>() {
|
private static final Map<Character, Integer> 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) {
|
private static int romanSymbolToInt(final char symbol) {
|
||||||
return ROMAN_TO_INT.computeIfAbsent(symbol, c -> { throw new IllegalArgumentException("Unknown Roman symbol: " + c); });
|
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:
|
||||||
|
* <ol>
|
||||||
|
* <li>Iterate over the string from right to left.</li>
|
||||||
|
* <li>For each character, convert it to an integer value.</li>
|
||||||
|
* <li>If the current value is greater than or equal to the max previous value, add it.</li>
|
||||||
|
* <li>Otherwise, subtract it from the sum.</li>
|
||||||
|
* <li>Update the max previous value.</li>
|
||||||
|
* <li>Return the sum.</li>
|
||||||
|
* </ol>
|
||||||
*
|
*
|
||||||
* @param a Roman number string
|
* @param roman the Roman numeral string
|
||||||
* @return integer
|
* @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) {
|
public static int romanToInt(String roman) {
|
||||||
a = a.toUpperCase();
|
if (roman == null) {
|
||||||
char prev = ' ';
|
throw new NullPointerException("Input cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
roman = roman.toUpperCase();
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
int maxPrevValue = 0;
|
||||||
int newPrev = 0;
|
for (int i = roman.length() - 1; i >= 0; i--) {
|
||||||
for (int i = a.length() - 1; i >= 0; i--) {
|
int currentValue = romanSymbolToInt(roman.charAt(i));
|
||||||
char c = a.charAt(i);
|
if (currentValue >= maxPrevValue) {
|
||||||
|
sum += currentValue;
|
||||||
if (prev != ' ') {
|
maxPrevValue = currentValue;
|
||||||
// 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;
|
|
||||||
} else {
|
} else {
|
||||||
// subtract upcoming number until upcoming number not greater than prev max
|
sum -= currentValue;
|
||||||
sum -= currentNum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
|
@ -8,16 +8,31 @@ import org.junit.jupiter.api.Test;
|
|||||||
public class RomanToIntegerTest {
|
public class RomanToIntegerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRomanToInteger() {
|
public void testValidRomanToInteger() {
|
||||||
assertEquals(1994, RomanToInteger.romanToInt("MCMXCIV"));
|
assertEquals(1994, RomanToInteger.romanToInt("MCMXCIV"));
|
||||||
assertEquals(58, RomanToInteger.romanToInt("LVIII"));
|
assertEquals(58, RomanToInteger.romanToInt("LVIII"));
|
||||||
assertEquals(1804, RomanToInteger.romanToInt("MDCCCIV"));
|
assertEquals(1804, RomanToInteger.romanToInt("MDCCCIV"));
|
||||||
|
assertEquals(9, RomanToInteger.romanToInt("IX"));
|
||||||
|
assertEquals(4, RomanToInteger.romanToInt("IV"));
|
||||||
|
assertEquals(3000, RomanToInteger.romanToInt("MMM"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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("Z"));
|
||||||
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MZI"));
|
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MZI"));
|
||||||
assertThrows(IllegalArgumentException.class, () -> RomanToInteger.romanToInt("MMMO"));
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user