Задачи на Python: обучение через практику

Раздел: Обучение Python -> Задачи по программированию

Задача на Python: проверка строки на палиндром

Палиндромом называют строку, которая читается одинаково в обоих направлениях (например, “radar” или “шалаш”). Самое эффективное решение в Python использует срез для обращения строки. Этот метод работает за O(n) и требует минимального объёма кода.

def is_palindrome(s):
    return s == s[::-1]

Python programming tasks (задачи по программированию на python)

print(is_palindrome("radar"))  # True
print(is_palindrome("hello"))  # False

задачи на python c решением (задачи на python с решением)

Типичные ошибки. Забывают о регистре: “Radar” вернёт False, хотя по смыслу это палиндром. Перед проверкой следует приводить строку к одному регистру. Также срез создаёт копию строки, что при очень больших объёмах данных может увеличить потребление памяти.

Как проверить палиндром без использования встроенного обращения?

Можно организовать цикл, сравнивая символы с обоих концов строки. Этот способ более нагляден для новичков и не требует дополнительной памяти для обратной копии.

def is_palindrome_loop(s):
    left, right = 0, len(s) - 1
    while left < right:
        if s[left] != s[right]:
            return False
        left += 1
        right -= 1
    return True
print(is_palindrome_loop("level"))  # True
print(is_palindrome_loop("test"))   # False

Частые проблемы. Пропуск обновления указателя right приводит к бесконечному циклу. Необходимо учитывать пустые строки или строки из одного символа – функция корректно вернёт True. Цикл работает медленнее среза из-за накладных расходов на выполнение Python-операций, но для большинства задач разница незаметна.

Как игнорировать пробелы, знаки препинания и регистр при проверке палиндрома?

Реальные строки часто содержат пробелы, заглавные буквы и символы пунктуации. Для корректной проверки необходимо очистить строку от лишних символов и привести всё к нижнему регистру.

import re

def is_palindrome_cleaned(s):
    cleaned = re.sub(r'[^a-zA-Zа-яА-ЯёЁ0-9]', '', s).lower()
    return cleaned == cleaned[::-1]
print(is_palindrome_cleaned("A man, a plan, a canal: Panama"))  # True
print(is_palindrome_cleaned("Was it a car or a cat I saw?"))    # True
print(is_palindrome_cleaned("Hello, World!"))                  # False

Возможные затруднения. Регулярное выражение может быть избыточным для простых случаев. Если требуется учитывать только буквы, можно использовать строковый метод isalpha() в фильтре. При работе с многобайтовыми кодировками (например, с эмодзи) регулярное выражение требует доработки. Использование модуля re замедляет выполнение на больших текстах.

Как реализовать проверку палиндрома рекурсивно?

Рекурсивный подход хорошо демонстрирует идею “разделяй и властвуй”, но для длинных строк может привести к переполнению стека вызовов.

def is_palindrome_rec(s):
    if len(s) <= 1:
        return True
    if s[0] != s[-1]:
        return False
    return is_palindrome_rec(s[1:-1])
print(is_palindrome_rec("racecar"))  # True
print(is_palindrome_rec("python"))   # False

Ограничения рекурсии. По умолчанию глубина рекурсии в Python ограничена 1000 вызовами. Для строк длиннее 1000 симвонов функция приведёт к ошибке RecursionError. Этот способ подходит только для обучения или заведомо коротких строк. Для производственного кода лучше использовать итеративные решения.

Расширенные примеры работы с палиндромами

1. Проверка палиндрома для целых чисел

Числа также могут быть палиндромами, например, 121 или 12321. Решение строится на обратном формировании числа.

Пример
def is_palindrome_number(x):
    if x < 0:
        return False
    original = x
    reversed_num = 0
    while x > 0:
        digit = x % 10
        reversed_num = reversed_num * 10 + digit
        x //= 10
    return original == reversed_num
print(is_palindrome_number(121))   # True
print(is_palindrome_number(-121))  # False (отрицательные числа не считаются)
print(is_palindrome_number(10))    # False

2. Поиск всех палиндромов в тексте

Задача найти все слова или подстроки, являющиеся палиндромами, в заданном тексте. Следующий код выделяет слова длиннее одного символа.

Пример
import re

def find_palindromes(text):
    words = re.findall(r'\b\w+\b', text)
    palindromes = []
    for word in words:
        if word.lower() == word.lower()[::-1] and len(word) > 1:
            palindromes.append(word)
    return palindromes

text = "level radar hello madam world"
print(find_palindromes(text))  # ['level', 'radar', 'madam']
['level', 'radar', 'madam']

3. Палиндром с использованием двусторонней очереди (collections.deque)

Модуль collections предоставляет структуру данных deque, которая позволяет эффективно извлекать элементы с обоих концов.

Пример
from collections import deque

def is_palindrome_deque(s):
    dq = deque(s)
    while len(dq) > 1:
        if dq.popleft() != dq.pop():
            return False
    return True

print(is_palindrome_deque("racecar"))  # True
print(is_palindrome_deque("python"))   # False
True
False

4. Проверка палиндрома с учётом юникода (эмодзи, кириллица)

Регулярное выражение для удаления всего, кроме букв, должно корректно обрабатывать любые алфавиты. Пример для русского и английского.

Пример
import re

def is_palindrome_unicode(s):
    # Удалить всё, кроме букв и цифр любых языков
    cleaned = re.sub(r'[^\w]', '', s, flags=re.UNICODE).lower()
    return cleaned == cleaned[::-1]

print(is_palindrome_unicode("А роза упала на лапу Азора"))  # True
print(is_palindrome_unicode("???"))                         # True (эмодзи тоже 'буквы' с точки зрения \w)
True
True

Задачи на Python с решением - comments

En
задачи на python c решением (python)