DocsHub
PythonBeginner

Palindrome Checker

Learn how to check if a string or number is a palindrome in Python.

Palindrome Checker

Problem

A palindrome is a word, number, or sentence that reads the same forwards and backwards.

Input:  "racecar"
Output: True

Input:  "hello"
Output: False

Input:  "A man a plan a canal Panama"
Output: True   (ignoring spaces and case)

Input:  12321
Output: True

Input:  12345
Output: False

Logic

  1. Clean the input — remove spaces, convert to lowercase
  2. Compare the cleaned string with its reverse
  3. If they match — it is a palindrome
  4. If they do not — it is not

Flow

Yes No Start Clean the inputremove spaces, lowercase Reverse the cleaned string cleaned == reversed? Return True Return False

Solution 1 — using string slicing

Clean the string, reverse it with [::-1], compare.

def is_palindrome(s):
    # convert to string in case a number is passed
    s = str(s)

    # clean — lowercase and remove spaces
    cleaned = s.lower().replace(" ", "")

    # reverse the cleaned string
    reversed_str = cleaned[::-1]

    # compare — if same forwards and backwards it is a palindrome
    return cleaned == reversed_str


# strings
print(is_palindrome("racecar"))                    # True
print(is_palindrome("hello"))                      # False
print(is_palindrome("A man a plan a canal Panama")) # True
print(is_palindrome("Madam"))                      # True

# numbers
print(is_palindrome(12321))   # True
print(is_palindrome(12345))   # False

Code Execution — Solution 1

Trace through is_palindrome("A man a plan a canal Panama"):

StepCodeResult
Convertstr(s)"A man a plan a canal Panama"
Lowercase.lower()"a man a plan a canal panama"
Remove spaces.replace(" ", "")"amanaplanacanalpanama"
Reverse[::-1]"amanaplanacanalpanama"
Comparecleaned == reversed_strTrue

Trace through is_palindrome("hello"):

StepCodeResult
Convertstr(s)"hello"
Lowercase.lower()"hello"
Remove spaces.replace(" ", "")"hello"
Reverse[::-1]"olleh"
Compare"hello" == "olleh"False

Solution 2 — using a loop with two pointers

Use two pointers — one starting from the left, one from the right. Move them toward each other comparing characters. If any pair does not match — not a palindrome.

def is_palindrome(s):
    # convert and clean
    s = str(s).lower().replace(" ", "")

    # left pointer starts at beginning
    left = 0
    # right pointer starts at end
    right = len(s) - 1

    while left < right:
        # compare character at left with character at right
        if s[left] != s[right]:
            return False   # mismatch found — not a palindrome

        left += 1    # move left pointer forward
        right -= 1   # move right pointer backward

    # all pairs matched — it is a palindrome
    return True


print(is_palindrome("racecar"))                     # True
print(is_palindrome("hello"))                       # False
print(is_palindrome("A man a plan a canal Panama")) # True
print(is_palindrome(12321))                         # True
print(is_palindrome(12345))                         # False

Code Execution — Solution 2

Trace through is_palindrome("racecar"):

s = "racecar" — length 7, indexes 0 to 6

Stepleftrights[left]s[right]Match?
1st06"r""r"Yes
2nd15"a""a"Yes
3rd24"c""c"Yes
4th33left < right is FalseStop

All pairs matched — return True

Trace through is_palindrome("hello"):

s = "hello" — length 5, indexes 0 to 4

Stepleftrights[left]s[right]Match?
1st04"h""o"No — return False

Mismatch on first comparison — immediately returns False.

The two-pointer approach is more efficient than reversing the whole string. It stops as soon as it finds a mismatch — it does not need to finish checking all pairs. For very long strings this matters.


Solution 3 — using recursion

Check the first and last characters. If they match, check the remaining middle string recursively.

def is_palindrome(s):
    # clean only on first call — convert and strip spaces
    s = str(s).lower().replace(" ", "")

    def check(s):
        # base case — empty string or single character is always a palindrome
        if len(s) <= 1:
            return True

        # if first and last characters do not match — not a palindrome
        if s[0] != s[-1]:
            return False

        # check the middle part — remove first and last characters
        return check(s[1:-1])

    return check(s)


print(is_palindrome("racecar"))                     # True
print(is_palindrome("hello"))                       # False
print(is_palindrome("A man a plan a canal Panama")) # True
print(is_palindrome(12321))                         # True

Code Execution — Solution 3

Trace through is_palindrome("racecar"):

check("racecar")
  s[0]="r", s[-1]="r" → match
  → check("aceca")
       s[0]="a", s[-1]="a" → match
       → check("cec")
            s[0]="c", s[-1]="c" → match
            → check("e")
                 len("e") <= 1 → True ✅
            return True
       return True
  return True
return True

Trace through is_palindrome("hello"):

check("hello")
  s[0]="h", s[-1]="o" → mismatch
  return False ✅

Solution 4 — handling punctuation too

A more complete version — strips spaces, punctuation, and handles case. Useful for real sentences.

import re

def is_palindrome(s):
    # convert to string
    s = str(s)

    # remove everything except letters and numbers
    # re.sub replaces all non-alphanumeric characters with ""
    cleaned = re.sub(r"[^a-zA-Z0-9]", "", s).lower()

    # compare with its reverse
    return cleaned == cleaned[::-1]


print(is_palindrome("racecar"))                       # True
print(is_palindrome("A man, a plan, a canal: Panama")) # True
print(is_palindrome("Was it a car or a cat I saw?"))   # True
print(is_palindrome("hello"))                          # False
print(is_palindrome(12321))                            # True

Code Execution — Solution 4

Trace through is_palindrome("A man, a plan, a canal: Panama"):

StepCodeResult
Inputs"A man, a plan, a canal: Panama"
Remove non-alphanumericre.sub(...)"AmanaplanacanalpanaMa"
Lowercase.lower()"amanaplanacanalpanama"
Reverse[::-1]"amanaplanacanalpanama"
Comparecleaned == reversedTrue

re.sub(r"[^a-zA-Z0-9]", "", s) means — replace any character that is NOT a letter or digit with an empty string. The ^ inside [] means NOT. This handles commas, periods, colons, exclamation marks — anything that is not part of the actual word.


Which solution to use?

SolutionHowBest when
Solution 1[::-1] slicingClean and readable — most common
Solution 2Two pointersEfficient — stops early on mismatch
Solution 3RecursionUnderstanding recursive thinking
Solution 4Regex cleaningReal sentences with punctuation

Output

True
False
True
True
True
False

On this page