Как я могу игнорировать пробелы, знаки препинания и все символы, отличные от букв, при проверке палиндрома?

Мне нужно проверить палиндром в отдельном классе, но игнорировать неалфавитные символы. Так, например, радар по-прежнему будет соответствовать требованиям, если будет написано r, a, d, a, r.

Я считаю, что мог бы использовать регулярное выражение, но я не знаю, как это сделать.

Вот что у меня есть до сих пор,

 public static boolean isNonAlpha(char c) {
    return (c == '-' || c == '.' || c == ' ' || c == ')' || c == '(') || c == '<' || c == '>' || c == ',';
}

public static String checkInput(String test){
    int startChar = 0;
    int endChar = test.length() - 1;
    while (startChar < endChar) {
        if (test.charAt(startChar) != test.charAt(endChar)) {
            System.out.println("Your word is not a palindrome.");
            System.exit(0);
        } else {
            if (test.charAt(startChar) == test.charAt(endChar))
                startChar++;
                endChar--;
        }
    }
    System.out.println("Your word is indeed a palindrome.");        
    return test;

}

Я застрял в том, как включить мой метод isNonAlpha или как использовать регулярное выражение


person Will Kerbusch    schedule 28.02.2016    source источник
comment
Стандартные регулярные выражения не могут обнаруживать палиндромы, поскольку они требуют памяти (до неограниченного значения) того, что было принято ранее. stackoverflow.com/questions/233243/ Однако на этой странице есть некоторые реализации   -  person Joseph Young    schedule 29.02.2016
comment
Возможно, это можно сделать в реализации регулярных выражений Java, как показано на некоторых языках, но технически они не являются обычными.   -  person Joseph Young    schedule 29.02.2016
comment
Удалить все неалфавитные символы и используйте обычный код проверки палиндрома. См. эту демонстрацию. Это работает, как ожидалось?   -  person Wiktor Stribiżew    schedule 29.02.2016


Ответы (1)


Вы можете использовать этот шаблон с методом matches (добавьте параметр без учета регистра, если хотите):

(?:[^a-z]*([a-z])(?=.*(\1[^a-z]*\2?+)$))+[^a-z]*[a-z]?[^a-z]*\2

Если вы хотите, чтобы совпадала и одна буква, добавьте |[^a-z]*[a-z][^a-z]* в конце.

демонстрация regexplanet (Java)
демонстрационное регулярное выражение101

Детали:

Идея состоит в том, чтобы захватить одну за другой каждую букву из начала строки в группе 1 и каждый раз проверять вперед, присутствует ли та же буква в конце. Группа захвата 2 находится в режиме просмотра и захватывает в конце строки ее собственное содержимое (из предыдущего повторения) и новую букву. При каждом повторении группа захвата 2 увеличивается с новой буквой (и другими символами, не являющимися буквами).

(?: # repeated non capturing group
    [^a-z]* # eventual other character before a letter
    ([a-z]) # the letter is captured in group 1
    (?=  # lookahead (to check the end of the string)
        .* 
        (
            \1      # backreference capture group1: the letter at the beginning
            [^a-z]* # other characters
            \2?+    # backreference capture group2: optional but possessive
                    # (that acts like a kind of conditional: if the group 2 already
                    # exists, it matches, otherwise not)
        )
        $  # anchor for the end of the string
    )
)+
[^a-z]*[a-z]?[^a-z]* # an eventual letter in the middle
\2 # backreference capture group 2

(В методе matches якоря неявные.)

person Casimir et Hippolyte    schedule 28.02.2016