RajveerParikh
RajveerParikh

Reputation: 111

Java - Roman Numeral validity

I am writing a program to add two roman numerals without converting to any bases. I have everything working except I am not sure how to check if my input String is a valid roman numeral or not.

These are the rules to check validity:

  1. Five in a row of any digit is not allowed
  2. Some digits are allowed in runs of up to 4. They are I,X,C, and M. The others (V,L,D) can only appear singly.
  3. Some lower digits can come before a higher digit, but only if they appear singly. E.g. "IX" is ok but "IIIX" is not.
  4. But this is only for pairs of digits. Three ascending numbers in a row is invalid. E.g. "IX" is ok but "IXC" is not.
  5. A single digit with no runs is always allowed

I have not really been able to make much progress with this step and don't have anything working yet. Any help would be great!

Upvotes: 1

Views: 5610

Answers (3)

Jeff_Alieffson
Jeff_Alieffson

Reputation: 2882

Why not use regular expression:

boolean valid = word.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$");

Look at the post of paxdiablo: How do you match only valid roman numerals with a regular expression?

Upvotes: 9

RajveerParikh
RajveerParikh

Reputation: 111

This is what I have come up with based on my rules. Any thoughts on refactoring this to make it simpler?

public static boolean checkValidity (String s1, HashSet<Character> romanNumerals){
    HashSet<Character> alreadyContained = new HashSet<Character>();
    if (s1.length() == 1 && romanNumerals.contains(s1.charAt(0))){
        return true;
    }
    int i = 0;
    while (i < s1.length()){
        if (s1.charAt(i) == 'M'){
            if (alreadyContained.contains('M')){
                return false;
            }
            int count = 1;
            i++;
            while (s1.charAt(i) == 'M'){
                i++;
                count++;
            }
            alreadyContained.add('M');
            if (count >= 5){
                return false;
            }
        }
        else if (s1.charAt(i) == 'D'){
            if (alreadyContained.contains('D')){
                return false;
            }
            alreadyContained.add('D');
            if (!alreadyContained.contains('M')){
                alreadyContained.add('M');
            }
            i++;
            if ((i < s1.length()) && (s1.charAt(i) == 'D')){
                return false;
            }

        }
        else if (s1.charAt(i) == 'L'){
            if (alreadyContained.contains('L')){
                return false;
            }
            alreadyContained.add('L');
            if (!alreadyContained.contains('M')){
                alreadyContained.add('M');
            }
            if (!alreadyContained.contains('D')){
                alreadyContained.add('D');
            }
            if (!alreadyContained.contains('C')){
                alreadyContained.add('C');
            }
            i++;
            if ((i < s1.length()) && (s1.charAt(i) == 'L')){
                return false;
            }
        }
        else if (s1.charAt(i) == 'V'){
            if (alreadyContained.contains('V')){
                return false;
            }
            alreadyContained.add('V');
            if (!alreadyContained.contains('M')){
                alreadyContained.add('M');
            }
            if (!alreadyContained.contains('D')){
                alreadyContained.add('D');
            }
            if (!alreadyContained.contains('C')){
                alreadyContained.add('C');
            }
            if (!alreadyContained.contains('L')){
                alreadyContained.add('L');
            }
            if (!alreadyContained.contains('X')){
                alreadyContained.add('X');
            }
            i++;
            if ((i < s1.length()) && (s1.charAt(i) == 'V')){
                return false;
            }

        }
        else if (s1.charAt(i) == 'C'){
            if (alreadyContained.contains('C')){
                return false;
            }
            int count = 1;
            i++;
            if ((i < s1.length()) &&(s1.charAt(i) == 'M' || s1.charAt(i) == 'D')){
                i++;
            }
            else if (i < s1.length() && s1.charAt(i) == 'C'){
                while ((i < s1.length()) && (s1.charAt(i) == 'C')){
                    i++;
                    count++;
                }
            }
            alreadyContained.add('C');
            if (!alreadyContained.contains('M')){
                alreadyContained.add('M');
            }
            if (!alreadyContained.add('D')){
                alreadyContained.add('D');
            }
            if (count >= 5){
                return false;
            }
        }
        else if (s1.charAt(i) == 'X'){
            if (alreadyContained.contains('X')){
                return false;
            }
            int count = 1;
            i++;
            if ((i < s1.length()) && (s1.charAt(i) == 'D' || s1.charAt(i) == 'M')){
                return false;
            }
            while ((i < s1.length()) && s1.charAt(i) == 'X'){
                i++;
                count++;
            }
            alreadyContained.add('X');
            if (count >= 5){
                return false;
            }
        }
        else if (s1.charAt(i) == 'I'){
            if (alreadyContained.contains('I')){
                return false;
            }
            alreadyContained.add('I');
            i++;
            int count = 1;
            if ((i < s1.length()) && (s1.charAt(i) != 'I' && s1.charAt(i) != 'X' && s1.charAt(i) != 'V')){
                return false;
            }
            else if (i < s1.length() && s1.charAt(i) == 'I'){
                while (i < s1.length() && s1.charAt(i) == 'I'){
                    i++;
                    count++;
                }
                if (count >= 4){
                    return false;
                }
            }
        }
        else if (!romanNumerals.contains(s1.charAt(i))){
            return false;
        }
    }
    return true;
}

Upvotes: 1

Ivantha
Ivantha

Reputation: 521

Loop through each character in the string. Use a if conditions to check which character it is. Use the if conditions to check for the roman numeral rule violations in the adjacent characters to the selected character.

for(int i = 0; i < s.length(); i++){  
    if (s[i] == 'V'){    
        **Check if the character before of after is also 'V'. Then it is a violation  
    }     
    else if(s[i] == 'L'){  
        **Conditions for 'L' etc.  
    }  
}  

Upvotes: 1

Related Questions