Will Kerbusch
Will Kerbusch

Reputation: 21

How can I ignore spaces, punctuation marks, and all characters different than letters while checking a palindrome?

I need to check a palindrome in a separate class but ignore non alphabet characters. So for example, radar would still qualify if it was written r,a,d,a,r

I believe I could use regex, but I don't know how.

Here is what I have so far,

 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;

}

I'm stuck on how to incorporate my isNonAlpha method, or how to use regex

Upvotes: 2

Views: 354

Answers (1)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

You can use this pattern with the matches method (add the case insensitive option if you want):

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

If you want to match a single letter too, add |[^a-z]*[a-z][^a-z]* at the end.

demo regexplanet (Java)
demo regex101

details:

The idea is to capture one by one each letters from the start of the string in group 1 and to check each time in a lookahead if the same letter is present at the end. The capture group 2 is in the lookahead and capture at the end of the string its own content (from the previous repetition) and the new letter. At each repetition the capture group 2 grows with the new letter (and other characters that are not letters).

(?: # 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

(With the matches method, anchors are implicit.)

Upvotes: 2

Related Questions