Living life by the motto, "You didn't get this far by giving up." It hasn't failed her yet.
Reversing a string is a common coding challenge, but what if you take it a step further and check for palindromes? What considerations need to be made?
If you’re not a taco cat, I suspect you’ll need a flashlight.
Palindromes! These fun little words and phrases always get a smile out of me. And in lieu of discussing the more tired and overdone coding challenge of reversing a string, I thought today we might discuss code that detects palindromes. After all, what is a palindrome but itself reversed?
But is it? Neither of the two palindromes I used at the beginning of this article can be simply reversed and check against itself, since both include space(s) and/or punctuation. That means we must find ourselves an appropriate regular expression, also known as a RegEx. Since many folks (myself included, I confess) would prefer to not write our own regular expressions, I’ll conclude this section of today’s assignment by pointing you all in the direction of two great resources for these: https://regex101.com/ and https://regexr.com/ . I’ll be tackling this challenge using JavaScript today, so the regular expression I will be using is /[^A-Z0-9]/gi
to remove everything except for letters and digits.
Okay, so we have a RegEx. All we need to do now is use the RegEx to remove the spaces and punctuation in the string we’re checking, then reverse and compare, right? Sure, you can certainly do it that way. But let’s aim for something a hair more challenging: Checking for a palindrome without reversing a string. After all, the moment we’ve been provided input, we have everything we need. Let’s dive in:
function demo() {
let userString = document.getElementById('userString').value;
userString = processInput(userString);
let result = checkForPalindrome(userString);
console.log(result);
}
function processInput(userString) {
userString = userString.replace(/[^A-Z0-9]/gi, "");
userString = userString.toLowerCase();
return userString;
}
function checkForPalindrome(userString) {
let middle = (userString.length % 2 == 1) ? (userString.length - 3) / 2 : (userString.length / 2) - 1;
for (let i = 0; i <= middle; i++) {
if (userString[i] != userString[userString.length - 1 - i]) return false;
}
return true;
}
As you can see, demo() gets user input from the DOM, runs it through processInput() and checkForPalindrome(), assigns a Boolean representing whether the user provided a palindrome, then logs that result to the console. Simple enough for our purposes. Let’s assume the user has provided as input the title of this article: “Eva, can I see bees in a cave?”
processInput() is straightforward and doesn’t need much discussion: ‘userString’ is taken in, and our RegEx is used to eliminate the spaces and punctuation, changing ‘userString’ to ‘EvacanIseebeesinacave.’ It then renders ‘userString’ into lowercase (‘evacaniseebeesinacave’), so we can compare apples to apples, and returns the rendered ‘userString.’ It’s the next function, checkForPalindrome() where the real magic happens.
And I don’t mean the magic of visualizing a taco cat
The first line of checkForPalindrome() is declaring ‘middle’ and setting it’s value using a ternary operator. What is this, exactly? This variable is where the last letters in the middle of the word are that we need to check. For ease of the eyes, let’s consider for a moment if the user had instead provided the other palindrome I used at the beginning of this article: “Taco cat.” Rendered, that would be ‘tacocat.’ What are the last letters we need to check? The c’s. There’s no point in comparing ‘o’ against itself, after all! So the ternary operator checks whether the length of ‘userInput’ is odd (i.e., userString.length % 2 == 1
). If so, the for-loop coming up only needs to iterate until 'i' is equal to (userString.length – 3) – 2
(remember, arrays use a ‘0’ base!); otherwise, the loop only needs to iterate until 'i' is equal to (userString.length / 2) – 1
.
Now we get to the for-loop itself, which is a one-liner once you get into the loop. Beginning with an index of ‘0’, we’ll loop while ‘i’ is less than or equal to ‘middle.’ For that loop, we’ll verify at each index whether userString[i]
is equal to userString[userString.length – 1 – i]
. Going back to our original example, ‘evacaniseebeesinacave,’ the index of ‘0’ would have us comparing the first letter and the last letter (‘e’ vs. ‘e’), the index of ‘1’ would have us comparing the next letters in (‘v’ vs. ‘v’), and so on. If we ever find the letters aren’t the same, then the user provided a non-palindrome, so we return ‘false,’ aborting the rest of the check. If we otherwise get through the whole for-loop, then we can return true; the user provided a palindrome.
You can also see bees in a cave when they’re by the mouth of the cave
And there you have it. Basic palindrome detection, and we never needed to reverse a string. As for exploring caves full of bees, I’ll leave that up to someone else, thanks.
0 Comments