Задания в классе

Тема занятия - итеративные рекурсивные функции.

В прошлый раз мы строили линейную древовидную рекурсию. В этой практике мы изучим метод оптимизации рекурсии, который уменьшает объем информации, требуемый для запоминания отложенных вычислений.

В общем случае, итеративный процесс - это такой процесс, состояния которого можно описать конечным числом переменных состояния плюс заранее заданное правило, определяющее как эти переменные состояния изменяются от шага к шагу, и плюс тест на завершение процесса.

Не смотря на то, что мы будем работать с Итерациями, но во всех заданиях запрещено использовать цикл for и while.

Факториал

В прошлый раз мы рассматривали обычное рекурсивное определение факториала:

$$ n!= \begin{cases} 1 & n = 0,\\ n \cdot (n-1)! & n > 0. \end{cases} $$

Очевидно, что его можно переписать в итеративной форме:

$$ n! = 1\cdot 2\cdot\ldots\cdot n =\prod_{k=1}^n k $$

Из определения мы можем заметить что:

произведение = счетчик * произведение
счетчик = счетчик + 1

Тогда

def factorial(n):
    return fact_iter(1, 1, n)

def fact_iter(product, counter, max_count):
    if counter > max_count:
        return product
    return fact_iter(counter * product, counter + 1, max_count)

Нарисуйте на доске процесс вычисления факториала. В этот раз у нас получился линейно итеративный процесс.

Фибоначчи

Математическое рекурсивное определение при переносе в программу даёт очень неэффективный алгоритм.

$$ F = \begin{cases} F(0)=1; \\ F(1) = 1; \\ F(n) = F(n-1) + F(n-2),\quad n > 1. \end{cases} $$

Идея: будем использовать две переменные a и b, которые в начале процесса зафиксируем значениями $Fib(1) = 1$ и $Fib(0) = 0$. Тогда на каждом шаге применяем одновременную трансформацию:

$$ \begin{aligned} a \leftarrow a + b \\ b \leftarrow a \end{aligned} $$