Найти тему
programmer's notes (python and more)

Программирование на Python. Рекурсия. Генерация списков

Доброго времени суток, читатели, зрители моего канала programmer's notes. Не забывайте подписываться и писать свои комментарии к моим статьям и видео.

А это подборки моих материалов на канале

Пример рекурсивной задачи генерации списков

Продолжаем пополнять подборку по алгоритмам. И опять рекурсивный алгоритм.

Задача на первый взгляд частная, но в действительности она легко обобщается на более широкий спектр задач.

В чём суть проблемы? Есть множество пар целых чисел. Вводятся они следующим образом. В начале идёт число - количество пар. А далее пары, по одной в строке. Например

2
1 2
3 4

Нужно получить все списки, состоящие из чисел. Каждое число из своей пары. Для данного примера получим

[1, 3]
[1, 4]
[2, 3]
[2, 4]

Последовательность этих списков нам не важна, главное, чтобы они все были.

Кстати, легко показать, что количество таких списков будет равно 2^n, где n это количество пар. И вот тут, тем кто интересуется задачами ЕГЭ может прийти в голову мысль, что я хочу разобрать как раз одну из задач ЕГЭ. В которой нужно найти одну из сумм таких последовательностей, удовлетворяющей определённому условию. Сразу скажу: нет. Во-первых, постановка другая. Но самое главное то, что при n = 20 мы уже получим 1048576 вариантов списков. Для задач из ЕГЭ этот подход не годится. Но с другой стороны данный подход абсолютно общий и получив все варианты, мы можем найти суммы последовательностей, удовлетворяющих любым заранее заданным условиям.

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

Текст программы см. ниже
Текст программы см. ниже
primer84.py

Функция recg() как раз та рекурсивная функция, выполняющая основную работу по получению всех вариантов списков. Например для

4
1 2
3 4
5 6
7 8

Получим

[[1, 3, 5, 7], [1, 3, 5, 8], [1, 3, 6, 7], [1, 3, 6, 8], [1, 4, 5, 7], [1, 4, 5, 8], [1, 4, 6, 7], [1, 4, 6, 8], [2, 3, 5, 7], [2, 3, 5, 8], [2, 3, 6, 7], [2, 3, 6, 8], [2, 4, 5, 7], [2, 4, 5, 8], [2, 4, 6, 7], [2, 4, 6, 8]]

Вот они всевозможные искомые списки. Естественно их 16 (2 в степени 4).

Несколько, пояснений к программе выше.

  • В программе есть определённый компромисс между использованием глобальных переменных (lss, l1) и параметров рекурсивной функции. Можно в принципе обойтись вообще без параметров. Попробуйте.
  • Условие if i == n это как раз то условие, которое говорит нам, что получен очередной список, длина которого естественно равна n.
  • l1.pop() — выход из рекурсии на один шаг назад предполагает, что мы удаляем последний элемент, который был добавлен на данном шаге.
  • Обратите внимание вот на это lss.append(l1[:]). Это добавление очередного полученного списка. Но написать lss.append(l1) было бы ошибкой. Мы бы добавили не сам список, а ссылку на него. А l1 ведь постоянно меняется.

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

Ну в общем так. Надеюсь, я увлек вас рекурсиями.

Хорошего программирования. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.

Программисты не умирают, они уходят в бесконечную рекурсию
Программисты не умирают, они уходят в бесконечную рекурсию