Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Challenge 8 the palindrome detector #51

Merged
merged 4 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions solutions/challenge_8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Challenge: Palindrome Detector

## Description

The "Palindrome Detector" challenge involves determining if a given string
or bytes is a palindrome.
A palindrome is a word, phrase, or sequence that reads the same backward as
forward, ignoring spaces, punctuation, and case.

Write a function that takes a string or bytes as input and returns `True` if
it is a palindrome, and `False` otherwise.

For example:

- The string `A man, a plan, a canal, Panama` is a palindrome.
- The string `hello` is not a palindrome.
- The bytes `b"racecar"` is a palindrome.
- The bytes `b"hello"` is not a palindrome.

## Example

```python
is_palindrome("A man, a plan, a canal, Panama")
# Output: True (ignoring spaces, punctuation, and case)

is_palindrome("hello")
# Output: False (not a palindrome)

is_palindrome(b"racecar")
# Output: True (ignoring spaces, punctuation, and case)

is_palindrome(b"hello")
# Output: False (not a palindrome)
Empty file.
45 changes: 45 additions & 0 deletions solutions/challenge_8/palindrome_detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
A module for checking if a given string or bytes is a palindrome.

Module contents:
- is_palindrome: Determines if a string or bytes is a palindrome.

Created on 09/01/2025
Author: Semira Tesfai
"""

import re
from typing import Union


def is_palindrome(s: Union[str, bytes]) -> bool:
"""Determines if a given string or bytes is a palindrome.

Parameters:
s: Union[str, bytes], the input string or bytes to be checked

Returns -> bool: True if the input is a palindrome, False otherwise

Raises:
TypeError: If the input is not a string or bytes

Examples:
>>> is_palindrome("A man, a plan, a canal, Panama")
True
>>> is_palindrome("hello")
False
>>> is_palindrome(b"racecar")
True
>>> is_palindrome(b"hello")
False
"""
if not isinstance(s, (str, bytes)):
raise TypeError("Input must be a string or bytes")

if isinstance(s, bytes):
s = s.decode("utf-8") # Decode bytes to string

cleaned_s = re.sub(r"[^A-Za-z0-9]", "", s).lower()
return cleaned_s == cleaned_s[::-1]
Empty file.
83 changes: 83 additions & 0 deletions solutions/tests/challenge_8/test_palindrome_detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Unit tests for palindrome_detector.py

Created on 09/01/2025
Author: Semira Tesfai
"""

import unittest

from solutions.challenge_8.palindrome_detector import is_palindrome


class TestIsPalindrome(unittest.TestCase):
"""
Test cases for the is_palindrome function.
"""

def setUp(self):
"""
Set up any state tied to the test execution. Invoked for every test method.
"""
self.simple_palindromes = ["racecar", "madam"]
self.complex_palindromes = ["A Santa at NASA", "A man, a plan, a canal, Panama"]
self.non_palindromes = ["hello", "This is not a palindrome"]
self.bytes_palindromes = [b"racecar", b"madam"]
self.bytes_non_palindromes = [b"hello", b"This is not a palindrome"]

def test_simple_palindrome(self):
"""
Test that simple palindromes are correctly identified.
"""
for sp in self.simple_palindromes:
with self.subTest(sp=sp):
self.assertTrue(is_palindrome(sp))

def test_complex_palindrome(self):
"""
Test that complex palindromes are correctly identified.
"""
for cp in self.complex_palindromes:
with self.subTest(cp=cp):
self.assertTrue(is_palindrome(cp))

def test_non_palindrome(self):
"""
Test that non-palindromic words and phrases are correctly identified.
"""
for np in self.non_palindromes:
with self.subTest(np=np):
self.assertFalse(is_palindrome(np))

def test_bytes_palindrome(self):
"""
Test that palindromes with bytes input are correctly identified.
"""
for bp in self.bytes_palindromes:
with self.subTest(bp=bp):
self.assertTrue(is_palindrome(bp))

def test_bytes_non_palindrome(self):
"""
Test that non-palindromic words and phrases with bytes input are correctly identified.
"""
for bnp in self.bytes_non_palindromes:
with self.subTest(bnp=bnp):
self.assertFalse(is_palindrome(bnp))

def test_invalid_input(self):
"""
Test that invalid input raises the appropriate exception.
"""
with self.assertRaises(TypeError):
is_palindrome(12345)
with self.assertRaises(TypeError):
is_palindrome(None)

def tearDown(self):
"""
Tear down any state that was previously set up with a call to setUp().
"""
pass
Loading