Рекурсия и итераторы
Долги за прошлый раз
Ещё раз про eval(input())
Ещё раз про операцию () + про callable() и __call__()
Про рекурсию
Рекурсия и цикл. Теория vs. практика. Гвидо, Python и хвостовой вызов
- ⇒ максимальная глубина рекурсии
- ⇒ логарифмический критерий уместности рекурсии
Замещение рекурсии стеком. Пример: есть ли среди натуральных чисел Seq такие, что в сумме дают S. Рекурсивный вариант.
- S — неизменяемая часть, Seq, Res — изменяемая, значит, их надо сохранять в стек. Рекурсия — это цикл, которые продолжается до тех пор, пока рекурсивные вызовы не кончились. (здесь не тот порядок добавления, для полного соответствия надо в обратном)
Про генераторы
Вычислимые последовательности.
Как задать самому? Например, циклической сборкой, см. пример выше
iterator object, next(), StopIteration
протокол последовательности: методы .__getitem__() или .__iter__()
iter() от всего подряд
⇒ работа цикла for: сделать итератор и по нему ходить
Создание и использование генератора, (yield ⇒ функция, возвращающая генератор, а уж генератор yield-ит результаты)
Пример работы, return в генераторе
- Генератор — «одноразовая» последовательность
yield from, важность этой конструкции
Itertools (сколько успеем)
Бесконечные последовательности и частичные вычисления, itertools
- Обработка вычислимых последовательностей
- функциональное программирование
- Обзор
- Бесконечные последовательности
- Модификация последовательностей
- Комбинаторика
Д/З
TODO
Прочитать что Гвидо думает о хвостовых рекурсивных вызовах, про итераторы и генераторы, про yield from и про itertools
- (это не рекурсия, а вот итератор применить можно ☺)
EJudge: UniInterval 'Объединение отрезков'
Input:Вводится кортеж пар натуральных чисел. Это координаты отрезков на прямой. Рассмотрим объединение этих отрезков и найдём длину этого объединения (т. е. совокупную длину всех «закрашенных» нашими отрезками отрезков на прямой).
Output:(66, 91), (152, 230), (21, 81), (323, 342), (158, 211), (286, 332), (294, 330), (18, 58), (183, 236)
213
EJudge: BinPow 'Бинарное возведение в степень'
Input:Написать рекурсивную функцию BinPow(), которая принимает три параметра: python3-объект a, натуральное число 0<N<1000000, и некоторую ассоциативную бинарную функциюf(). Функция BinPow() реализует алгоритм бинарного возведения в степень (кроме нулевой степени). Результатом BinPow(a, n, f) будет применение f(x) к a n-1 раз. Более точно, BinPow(a, 1, f) == a, BinPow(a, 2, f) == f(a,a), BinPow(a, 3, f) == f(a,f(a, a)) == f(f(a, a), a) (в силу ассоциативности), … BinPow(a, n, f) == f(f(…f(a, a), …), a).
Output:print(BinPow(2,33,int.__mul__), 2**33) print(BinPow("Se", 7, str.__add__))8589934592 8589934592 SeSeSeSeSeSeSe
EJudge: IterPi 'Пи /кродёться/'
Input:Пользуясь формулой Лейбница для вычисления числа Пи:
написать бесконечный генератор pigen(), возвращающий последовательно 4, 4-4/3, 4-4/3+4/5, 4-4/3+4/5-4/7…;
Output:P=pigen() print(next(P), next(P), next(P), next(P), sep="\n")
4.0 2.666666666666667 3.466666666666667 2.8952380952380956
EJudge: ChainSlice 'Режем лазанью'
Input:Написать функцию chainslice(begin, end, seq0, seq1, …), которая принимает не менее трёх параметров: два целых числа и не менее одной последовательности. Рассмотрим последовательность seq, образованную всеми элементами seq0, затем — всеми элементами seq1, и т. д. Вернуть эта функция должна итератор, пробегающий элементы последовательности seq с №begin до №end-1 включительно.
Output:print(*(chainslice(17, 33, range(7), range(8), range(6), range(9), range(5))))
2 3 4 5 0 1 2 3 4 5 6 7 8 0 1 2
Д/З мне:
I = iter(Seq) old = next(I) for new in I: ...
вместо
