2016-06-11 3 views
-3

Я хочу написать функцию, чтобы проверить правильность заданной строки в римской презентации. Они много случаев, не являющихся разрешенных комбинаций: (я предполагаю, что данная строка будет представлять собой число от 1 до 3999)проверить достоверность номера в романе

  • Мы не можем иметь такой же характер, более чем в три раза подряд: экс : IIII неверно.
  • Некоторые комбинации не допускаются: DD является ложным ('D' + 'D' = 500 + 500 = 1000, которое равно M
  • Мы не можем вычеркнуть символ и добавить тот же символ сразу после: например, IXI неверное событие, если IX равно 9, оно не равно 9 + 1
  • Наиболее значимые цифры должны быть в начале не в середине или в конце. Пример: XM (для 1010) является ложным, а MX - правильный один.
  • и т.д ...

Итак, моя идея состояла в том, что вместо того, чтобы проверить для не допускаются комбинации, я буду писать все возможное допустимые комбинации и каждый раз, когда мы встречаем комбинацию, которая не входит в их число, мы вернем false. Это была моя идея. Неудобно то, что моя заключительная функция была очень длинной и не очень понятной.

Например, я написал первую функцию для проверки тысяч (если они существуют, конечно), функция затем возвращает индексы, которые я буду использовать для подстановки текущей строки, чтобы перейти к следующей части (которая будет сотни в этом случае):

private static int isThousandsValid(String str){ 
    int len = str.length(); 

    char a1 = str.charAt(0); 
    char a2 = (len >= 2)? str.charAt(1) : ' '; 
    char a3 = (len >= 3)? str.charAt(2) : ' '; 

    if (a1 == 'M' && a2 == 'M' && a3 == 'M') //if we met that combinatin 
     return 3; //we have to move after 3 digits to meet the beginning 
         //of the hundred digits 
    else if (a1 == 'M' && a2 == 'M') //same raisoning for other combinations 
     return 2; 

    else if (a1 == 'M') 
     return 1; 

    else if (a1 == 'D' || a1 == 'C' || a1 == 'L' || a1 == 'X' || a1 == 'V' || a1 == 'I' ) 
     return 0; 

    else return -1; 

} 

Затем я написал то же самое для сотен, десятков и единиц. Пример сотни:

private static int isHundredsValid(String str){ 
    if (str.isEmpty()) return 0; 
    int len = str.length(); 

    char a1 = str.charAt(0); 
    char a2 = (len >= 2)? str.charAt(1) : ' '; 
    char a3 = (len >= 3)? str.charAt(2) : ' '; 
    char a4 = (len >= 4)? str.charAt(3) : ' '; 

    if (a1 == 'C' && a2 == 'M') 
     return 2; 

    else if (a1 == 'D' && a2 == 'C' && a3 == 'C' && a4 == 'C') 
     return 4; 

    else if (a1 == 'D' && a2 == 'C' && a3 == 'C') 
     return 3; 

    else if (a1 == 'D' && a2 == 'C') 
     return 2; 

    else if (a1 == 'D') 
     return 1; 

    else if (a1 == 'C' && a2 == 'D') 
     return 2; 

    else if (a1 == 'C' && a2 == 'C' && a3 == 'C') 
     return 3; 

    else if (a1 == 'C' && a2 == 'C') 
     return 2; 

    else if (a1 == 'C') 
     return 1; 

    else if (a1 == 'L' || a1 == 'X' || a1 == 'V' || a1 == 'I' ) 
     return 0; 

    else return -1;  
} 

Тогда в моей последней функции, я пишу это:

public static boolean isValidRoman(String str){ 
    str = str.trim(); //remove spaces 
    if (str.isEmpty()) return false; 

    int index1 = isThousandsValid(str);  
    String str1 = mySubstring(str, index1); 

    int index2 = isHundredsValid(str1);  
    String str2 = mySubstring(str1, index2); 

    int index3 = isTensValid(str2);   
    String str3 = mySubstring(str2, index3); 

    int index4 = isUnitsValid(str3);   
    String str4 = mySubstring(str3, index4); 

    if (str1.isEmpty() || str2.isEmpty() || str3.isEmpty()) 
     return true; 

    if (index1 == -1 || index2 ==-1 || index3 == -1 || index4 == -1) 
     return false; 

    return str4.isEmpty(); //if we still have ANOTHER character after it terminates 
} 

Наконец «mySubstring» это простая функция, которую я использовал, чтобы реорганизовать и очистить свой код:

private static String mySubstring(String str, int index){ 
    if (index == -1) return str; 
    else 
     return str.substring(index); 
} 

У меня есть два основных вопроса: Эта функция кажется вам правильной? Я тестировал много примеров, но я не уверен (я не могу проверить все возможные комбинации 3999 ...)

Можно ли улучшить его? Просто сделать его более чистым или более читаемым? Есть ли более простой способ проверить достоверность римского номера, а не писать все эти случаи?

+0

Для обзора рабочего кода, [Просмотр Коды] (http://codereview.stackexchange.com/) является место, куда пойти. – Mephy

ответ

1

Я хотел бы пойти на кратко- и сумасшедшее решение и соответствовать строке, используя регулярное выражение:

public boolean isRoman(String s) 
{ 
    return !s.isEmpty() 
      && s.matches("M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})"); 
} 
+0

Если ваша проблема - это домашнее задание, вам следует серьезно изучить регулярные выражения и убедиться, что вы можете объяснить каждую часть регулярного выражения перед отправкой этого решения ... –

+0

Это работает, но я не очень хорошо это понял. Можете ли вы объяснить или показать мне ссылку, чтобы понять регулярное выражение в java? благодаря! – salamanka44

+0

Возможно, [wikipedia] (https://en.wikipedia.org/wiki/Regular_expression) может быть отправной точкой. Существует также [учебник по Java] (https://docs.oracle.com/javase/tutorial/essential/regex/). И тогда у вас всегда есть [javadoc] (https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html). Регулярные выражения являются хорошим краеугольным камнем в вашем профессиональном программном инструменте! –

Смежные вопросы