пятница, 12 сентября 2014 г.

определяем "палиндромичность" строки в python 2.7

Рассмотрим основные варианты определения, является ли строка палиндромом, т.е. горизонтально симметричной относительно середины строкой.

Первый вариант, с использованием слайсов
def is_pali(s):
    return s==s[::-1]

Выражение s[::-1] возвращает новую строку, состоящую из символов данной строки, взятых в обратном порядке.

Второй вариант, с использованием функции (на самом деле, класса) reversed.
def is_pali(s):
    return s==''.join(reversed(s))

Так как reversed(s) возвращает итератор, для сравнения с оригинальной строкой необходимо собрать на его основе новую строку, для этого используется строковый метод join.

Третий вариант, также с использованием reversed.
def is_pali(s):
    return all(map(lambda x:x[0]==x[1],zip(s,reversed(s))))

Zip возвращает список кортежей длины 2, где первым элементом (индекс 0) является N-ный символ исходной строки, вторым (с индексом 1) - N-ный символ обращенной строки. В случае равенства между собой элементов каждого из кортежей строка является палиндромом.

И последний вариант, с использованием рекурсии. Сравниваем первый и последний символы строки. Если они различны, строка не является палиндромом. Если они одинаковы, строка может быть палиндромом, чтобы убедиться в этом, рекурсивно обрабатываем строку, полученную из текущей отбрасыванием первого и последнего символов. Базовый случай рекурсии: пустая строка и строка длиной в один символ являются палиндромами, возвращаем истинное значение.
def is_pali(s):
    if len(s)<=1:
        return True
    if s[0]==s[-1]:
        return is_pali(s[1:-1])
    else:
        return False

Перепишем, используя short-circuit evaluation (ленивое вычисление логических выражений c and и or).
Если длина строки меньше единицы, сразу возвращаем True. Здесь подойдет or:
def is_pali(s):
    return len(s)<=1 or ...

Далее, если первый и последний символы одинаковы, возвращаем значение, которое отдаст рекурсивный вызов, иначе, возвращаем ложное значение. Здесь напрашивается and:
def is_pali(s):
    return len(s)<=1 or s[0]==s[-1] and is_pali(s[1:-1])

Вышеописанные функции, как и многие другие однострочные функции, можно здать в виде lambda-выражения.