A programmer writes a function to check if a string is a palindrome (ignoring case and non-alphanumeric characters). Which implementation correctly achieves this?
Trap 1: def is_pal(s): s = s.lower(); return s == ''.join(reversed(s))
This version normalizes case but leaves all punctuation and whitespace intact, so phrases like 'A man, a plan, a canal: Panama' will not be recognized because the comma, spaces, and colon remain in the comparison. The reversal via ''.join(reversed(s)) is valid and creates a fully reversed string, but the failure stems from omitting the alphanumeric-filter step. As a result, only strings consisting entirely of letters (after lowercasing) can pass, making it unsuitable for real-world phrases.
Trap 2: def is_pal(s): return s == s[::-1]
This bare version performs no normalization whatsoever, so it treats the input as raw characters and compares it to its reverse exactly. Common palindrome inputs like 'Racecar' fail due to the leading uppercase 'R', and phrases with spaces or punctuation are never recognized unless the caller has already sanitized them. It may work only for pre-lowercased, single-word strings with no punctuation, making it a fragile and incomplete solution.
Trap 3: def is_pal(s): s = s.lower(); return s == s[::-1]
This version applies .lower() to disregard case but then compares the still-unfiltered string against its reverse using slicing. It will reject classic palindrome phrases such as 'never odd or even' because spaces are retained and cause the forward and reversed strings to differ. The slicing reversal is efficient, but the missing alphanumeric filter is the critical flaw that keeps this from being a correct general palindrome checker.
- A
def is_pal(s): s = s.lower(); return s == ''.join(reversed(s))
Why wrong: This version normalizes case but leaves all punctuation and whitespace intact, so phrases like 'A man, a plan, a canal: Panama' will not be recognized because the comma, spaces, and colon remain in the comparison. The reversal via ''.join(reversed(s)) is valid and creates a fully reversed string, but the failure stems from omitting the alphanumeric-filter step. As a result, only strings consisting entirely of letters (after lowercasing) can pass, making it unsuitable for real-world phrases.
- B
def is_pal(s): s = ''.join(c for c in s if c.isalnum()).lower(); return s == s[::-1]
This is the correct palindrome checker because it first strips out every non-alphanumeric character with a generator expression and ''.join(), then lowercases the cleaned string. Comparing this normalized form to its extended-slice reverse s[::-1] accounts for spaces, punctuation, and mixed case in one clean pass. This is the robust, idiomatic approach expected for a general-purpose palindrome test.
- C
def is_pal(s): return s == s[::-1]
Why wrong: This bare version performs no normalization whatsoever, so it treats the input as raw characters and compares it to its reverse exactly. Common palindrome inputs like 'Racecar' fail due to the leading uppercase 'R', and phrases with spaces or punctuation are never recognized unless the caller has already sanitized them. It may work only for pre-lowercased, single-word strings with no punctuation, making it a fragile and incomplete solution.
- D
def is_pal(s): s = s.lower(); return s == s[::-1]
Why wrong: This version applies .lower() to disregard case but then compares the still-unfiltered string against its reverse using slicing. It will reject classic palindrome phrases such as 'never odd or even' because spaces are retained and cause the forward and reversed strings to differ. The slicing reversal is efficient, but the missing alphanumeric filter is the critical flaw that keeps this from being a correct general palindrome checker.