1

I'm writing a simple algorithm that checks if a string is a palindrome in javascript. This is what I have so far:

var isPalindrome = function(s) {
    let i=0;
    let j=s.length-1;
    while (i < s.length && j >= 0) {
        while (s[i].toLowerCase().match('[a-z0-9].') === false && i < s.length) {
            i++;
        }
        while (s[j].toLowerCase().match('[a-z0-9].') === false && j >= 0) {
            j--;
        }
        if ((s[i].toLowerCase()) !== (s[j].toLowerCase())) {
            console.log(s[i].toLowerCase());
            console.log(s[j].toLowerCase());
            return false
        } else {
            i++;
            j--;
        }
    }
    return true;
};

The expected input can include non alphanumeric characters, e.g. .'";/, or whitespace, but they are to be ignored. For example,

"A man, a plan, a canal: Panama"

should return true, since once the string is stripped of any whitespace and punctuation, etc. it is a valid palindrome. My issue is that when I run this code on this example input, the console.log statements in the if loop above prints:

[whitepsace (a blank line)]
m

indicating in the first while loop, the statement s[i].toLowerCase().match('[a-z0-9].') is returning true when s[i] is a whitespace, causing the function to incorrectly return false, which doesn't make sense to me as my regex doesn't include whitespace in its character class. Why is this statement returning true for a whitespace character?

2
  • 1
    match('[a-z0-9].') matches for every character because of the unescaped .. match('[a-z0-9]\.') is your way to go Commented Apr 25, 2021 at 18:52
  • PS: I would suggest to replace every character you don't want and then run your algo without any checks. (This might even be faster than testing every character individually with a regex) Commented Apr 25, 2021 at 18:53

1 Answer 1

2

Even if you correct the regular expression (by removing the dot), the inner while loops may exit because you reach the end of the array, leaving you with out of range index references in the comparison that follows in the if.

It is better to just remove the characters that are not alphanumeric, and to turn everything to lower case even before you start the loop. Furthermore, you can stop the outer loop when i crosses over j:

var isPalindrome = function(s) {
    s = s.toLowerCase().replace(/[^a-z\d]/g, "");
    for (let i = 0, j = s.length - 1; i < j; i++, j--) {
        if (s[i] !== s[j]) {
            console.log(s[i], s[j]);
            return false;
        }
    }
    return true;
};

console.log(isPalindrome("A man, a plan, a canal: Panama"));

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.