Skip to content

Practice problem

Valid Palindrome

Easy

Solve in Python · graded against 3 sample tests and a hidden test set in your browser · Published

Problem Statement

You're given a single line of text that can mix letters, digits, spaces, and punctuation in any combination of upper and lower case. Decide whether that line is a palindrome once you ignore everything except letters and digits, and once you treat uppercase and lowercase letters as identical. Print true if, after that cleanup, the line reads the same from left to right as it does from right to left, and print false otherwise.

Input Format

The input is exactly one line: the string to check. That line can be empty (zero characters), and when it isn't empty it can include upper- and lowercase English letters, digits 0-9, spaces, and punctuation marks such as commas, periods, apostrophes, and colons. Read the whole line exactly as given — the spaces and punctuation are still part of the line even though the comparison itself will skip over them.

Output Format

Print exactly one line containing the word true or the word false, in lowercase and with no surrounding quotes or extra text. Print true if the cleaned-up version of the input (letters and digits only, lowercased) is a palindrome, and false if it is not.

Example Walkthrough

Use the first sample, A man, a plan, a canal: Panama. Picture two pointers, one starting at the first character (index 0, A) and one at the last character (index 29, the final a). Both are letters, so we lowercase and compare them: a equals a, a match, and both pointers move one step inward. This continues character by character — m/m, then a/a, then n/n — until the left pointer lands on the comma at index 5. A comma isn't a letter or digit, so the left pointer skips over it and the following space, landing on a at index 7, which matches the right pointer's a. The same skipping happens later on the right side too: as the right pointer moves inward it eventually sits on the space at index 23 and then the colon at index 22, skips both, and lands on l at index 21, which matches the left pointer's l. The two pointers keep stepping inward, matching pair after pair, until they meet at the c in the middle (index 17). Since every pair that was compared matched and the pointers met without ever finding a mismatch, the line is a palindrome, so we print true.

Approach

One way to solve this is to build a cleaned-up copy of the string first: walk through the original line once, keep only the characters where .isalnum() is true, lowercase each of them, and collect the results into a new string. Once you have that cleaned string, checking whether it's a palindrome is just a matter of comparing it to its own reverse. This is easy to reason about, but it uses extra space proportional to the length of the input, since you're storing a whole second copy of it.

The two-pointer technique avoids that extra copy. Keep one index starting at the front of the original string and another starting at the back, and move them toward each other. At each step, if the character under the left pointer isn't a letter or digit, advance just the left pointer past it without comparing anything yet; do the same for the right pointer if its character isn't a letter or digit. Once both pointers are sitting on a letter or digit, compare them case-insensitively — if they differ, you can stop immediately and report false, since a single mismatch is enough to rule out a palindrome. If they match, move both pointers one step further inward and repeat.

The moment the two pointers meet or cross, every pair of characters that could possibly mismatch has already been checked and none of them did, so the string is confirmed to be a palindrome and you can print true. Skipping non-alphanumeric characters in place, rather than removing them into a new string first, is what keeps this version from needing any extra memory beyond the original input and a couple of index variables.

Common Mistakes

  • Filtering with a check that excludes digits. It's easy to write a condition that only keeps letters (for example, checking .isalpha() instead of .isalnum()), forgetting that digits also count as alphanumeric characters for this problem. A short input like 0P shows the difference clearly: correctly keeping both characters gives 0p, which reversed is p0 — not a match, so the answer is false — but dropping the digit leaves only p, a single character that trivially looks like a palindrome.
  • Comparing characters without lowercasing them first. If you compare text[left] to text[right] directly instead of comparing their lowercased forms, a perfectly valid palindrome where the case differs between the two matching positions — like the capital P in Panama lining up with a lowercase p elsewhere — will be reported as a mismatch even though it shouldn't be.
  • Skipping only one non-alphanumeric character at a time with a single if instead of a loop. Punctuation and spaces often appear back-to-back, like the : in canal: Panama. If your pointer-skipping logic only steps past one such character before immediately trying to compare, it will end up comparing a space or punctuation mark against a letter and report a false mismatch — the skipping step needs to keep advancing the pointer until it actually lands on a letter or digit.

Sample tests

Sample 1

Input

A man, a plan, a canal: Panama

Expected output

true

Removing spaces and punctuation and lowercasing everything gives "amanaplanacanalpanama", which reads the same forwards and backwards.

Sample 2

Input

race a car

Expected output

false

Removing the spaces gives "raceacar"; reversed that is "racaecar", which does not match, so the line is not a palindrome.

Sample 3

Input

Was it a car or a cat I saw?

Expected output

true

Removing spaces and punctuation and lowercasing everything gives "wasitacaroracatisaw", which reads the same forwards and backwards.

Your solution

Run tries the first sample. Submit grades against every sample and the hidden tests. Your code is saved in this browser as you go.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

Read the idea first

More problems

All practice problems →