Проверить программы онлайн · файлы остаются в браузере

Рекурсия — практикум

10 класс, углублённый уровень. Занятие двенадцатое. Функция, которая зовёт сама себя: база и шаг, стек вызовов, печать на спуске и на подъёме, дерево вызовов, как у фрактала, и функция, заданная формулой, — как в задании 16 ЕГЭ.

План на пару. Сначала тренажёр: шесть коротких задач о том, как работает рекурсия, — значение функции, печать до и после вызова, сколько вызовов, функция по формуле, где программа упадёт, глубина стека. Потом три программы, в каждой две рекурсивные функции с оговорёнными именами. Проверяет их оболочка Проверка.bat из общей папки: она запускает программу на девяти наборах данных, смотрит, что функции действительно зовут сами себя и обходятся без циклов, а потом зовёт каждую напрямую. Интернет не нужен.

Часть 1. Тренажёр: как работает рекурсия

Шесть типов задач, по одной на каждый. Считать в уме или на бумаге: выпиши вызовы столбиком — каждый следующий ступенькой правее, — дойди до базы, а потом поднимайся и подставляй ответы снизу вверх. Ответ — всё напечатанное через пробел, или число, о котором спрашивают. Ошибся — ниже появится разбор рисунком: вызовы лесенкой по глубине стека, что каждый вернул, где была печать, — и кнопка «Новые числа»: реши такую же ещё раз.

0 верно из 6

Часть 2. Как устроена рекурсия

База и шаг

фрагмент программы — набери его сам

Сумма цифр 3815 — это сумма цифр 381 плюс 5. Задача сведена к такой же, но меньшей, — и так до однозначного числа, у которого ответ известен. Без базы вызовы не кончатся; шаг, который к базе не ведёт, — то же самое.

Стек вызовов

СпускЧто ждёт в стекеПодъём
digsum(3815)ждёт digsum(381), потом + 512 + 5 = 17
digsum(381)ждёт digsum(38), потом + 111 + 1 = 12
digsum(38)ждёт digsum(3), потом + 83 + 8 = 11
digsum(3)база — ответ сразу3

Каждый незаконченный вызов лежит в стеке со своим n и помнит, что ему осталось сделать. Ответ отдаётся тому, кто лежит под ним. Глубина стека — сколько вызовов ждут одновременно; у Python предел около тысячи, дальше — RecursionError.

Печать до и после вызова

фрагмент программы — набери его сам

print до вызова срабатывает на спуске, после — на подъёме, в обратном порядке. Остатки от деления на 2 появляются с конца, а стек сам разворачивает их в правильный порядок.

Два вызова в теле — дерево

фрагмент программы — набери его сам

Один вызов в теле даёт цепочку, два — дерево вызовов, как у фрактала: каждая ветка повторяет целое в уменьшенном виде. tree(3) — это 1 + 2 + 4 + 8 = 15 вызовов. Так рисуют дерево Пифагора, снежинку Коха, треугольник Серпинского.

Функция по формуле — задание 16 ЕГЭ

фрагмент программы — набери его сам

Формула переписывается в функцию дословно: случаи — это if, база — первый случай. Две функции могут звать друг друга — порядок def не важен, лишь бы оба стояли выше вызова. Считать на бумаге удобнее снизу вверх таблицей: F(1), F(2), F(3)…

Три ошибки рекурсии

Часть 3. Три программы

Задание 1 Цифровой корень

Сложим цифры числа, потом цифры суммы — и так, пока не останется одна цифра: 99 → 18 → 9. Эта цифра — цифровой корень. Напиши две рекурсивные функции: код возвращает сумму цифр код, а код — цифровой корень, через код. Программа читает натуральное число код (до 1012) и печатает сумму его цифр и цифровой корень.

Функции: код и код — обе возвращают число, обе рекурсивные, без циклов.

Вход

99

Вывод

Сумма цифр: 18
Цифровой корень: 9

Проверяется: рекурсия в обеих функциях; digsum и digroot напрямую — однозначные, 10, 99, двенадцать девяток, триллион.

Если застрял

код: база — однозначное число, оно само себе сумма цифр; шаг — код. код: однозначное число — само себе корень, иначе код.

Ловушка, ради которой это задание. Один вызов код — ещё не корень: у 99 сумма цифр 18, двузначная. Рекурсия в код и повторяет сложение столько раз, сколько нужно.

Задание 2 Двоичная запись

Последняя двоичная цифра числа — код, остальные — двоичная запись код. Напиши две рекурсивные функции: код возвращает двоичную запись код, записанную как обычное число (11 → 1011), а код — сколько единиц в этой записи. Программа читает целое код (0 ≤ n ≤ 1000000) и печатает его двоичную запись и число единиц. Функцию код не использовать.

Функции: код и код — обе возвращают число, обе рекурсивные, без циклов.

Вход

11

Вывод

Двоичная запись: 1011
Единиц: 3

Проверяется: рекурсия в обеих функциях; to_bin и ones напрямую — 0, 1, 2, 8, 255, 1024, миллион.

Если застрял

код: база — код (0 и 1 записываются сами собой); шаг — код: запись остальных цифр сдвигается на разряд влево, и справа приписывается последняя. код: база код, шаг код.

Ловушки, ради которых это задание. База код не ловит ноль: код зовёт код без конца. Приписать цифру не с той стороны — и запись выйдет задом наперёд.

Задание 3 Две функции по формуле

Так звучит задание 16 ЕГЭ. Функции заданы формулами:

F(1) = 1, G(1) = 1;
F(n) = F(n − 1) + 2·G(n − 1) при n > 1;
G(n) = F(n − 1) + G(n − 1) при n > 1.

Напиши функции код и код — дословно по формулам. Программа читает натуральное код (1 ≤ n ≤ 15) и печатает F(n) и G(n).

Функции: код и код — обе возвращают число, зовут себя и друг друга, без циклов.

Вход

4

Вывод

F: 17
G: 12

Проверяется: рекурсия в обеих функциях; F и G напрямую — n = 1, 2, 3, 5, 8, 12.

Если застрял

Каждый случай формулы — ветка: код, иначе код. Так же G. Проверь на бумаге: F(2) = 1 + 2 = 3, G(2) = 1 + 1 = 2.

Ловушки, ради которых это задание. База нужна обеим функциям. Внутри G — значения от код: вызов код оттуда уходит в вечный спуск. На n = 15 вызовов десятки тысяч — дерево ветвится; это ещё быстро, но для n = 40 такую рекурсию уже считают снизу вверх.

Часть 4. Сдача

  1. Файлы zadanie1.py … zadanie3.py лежат в твоей папке, отладочные print из них убраны.
  2. В общей папке двойной щелчок по Проверка.bat.
  3. «Найти мои файлы» → «Проверить всё».
  4. Покажи учителю два экрана: тренажёр наверху этой страницы и итог оболочки.
Если вместо окна открылся текст программы — файл открылся в IDLE как код. Нажми F5, окно появится.

Оболочка показывает, на каких данных программа ошиблась и что должна была вывести, есть ли в функциях рекурсия и нет ли циклов, а если не так ведёт себя функция — какой вызов что вернул и что должен был. Исправляй и проверяй снова, попыток сколько угодно. Отметка: три задания — «5», два — «4», одно — «3».

Подсказка: рекурсия

База и шаг

Рекурсивная функция зовёт сама себя. База — случай, где ответ даётся сразу, без вызова себя. Шаг — та же задача, но меньше: digsum(n // 10) + n % 10. Шаг обязан вести к базе.

Стек вызовов

Незаконченные вызовы ждут в стеке, у каждого своё n. Ответ отдаётся тому, кто лежит ниже. Глубина — сколько вызовов ждут одновременно; предел Python — около тысячи, дальше RecursionError.

Спуск и подъём

print до вызова — на спуске, сверху вниз; print после вызова — на подъёме, в обратном порядке. Остатки n % 2, напечатанные после вызова p(n // 2), дают двоичную запись по порядку.

Дерево вызовов

Два вызова в теле — дерево, как у фрактала: 1 + 2 + 4 + … вызовов. Считаются все вызовы, и те, что сразу упираются в базу.

Формула — задание 16 ЕГЭ

Случаи формулы — ветки if, база — первый случай. Две функции могут звать друг друга. На бумаге считать снизу вверх таблицей: F(1), F(2), F(3)…

Три ошибки

Нет базы — RecursionError. Шаг мимо базы (через два из нечётного) — то же. Забыт return — наверх уходит None и TypeError на None + n.

Материалы подготовлены с использованием технологий искусственного интеллекта.