Python составить все комбинации

Генерация всевозможных комбинаций из набора символов — комбинаторика в Python (itertools)

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

Что ж, в преддверии Нового года KOTOFF.net вновь расправляет крылья.

И сразу к делу. Рассмотрим всего 3 функции и их различия.

1. Нахождение всевозможных комбинаций из набора символов

Допустим, у нас есть некий алфавит из трёх букв (А, Б, В), и из него необходимо составить максимальное количество трёхзначных слов (комбинаций). Причём в данном случае буквы могут повторяться. Алфавит короткий, однако у нас получится составить целых 27 слов. На каждую позицию приходится по 3 варианта букв, соответственно, общее количество комбинаций можно посчитать так: n k (n — количество доступных символов в степени k — длина конечной комбинации) . Для нашего случая: 3 3 = 27

Теперь импортирую itertools и сгенерирую всё то, что выше считали руками, но теперь уже с помощью функции product():

from itertools import product for i in product('АБВ', repeat=3): print(''.join(i), end=' ')

Функция принимает два параметра (набор символов и длина конечного объекта). С помощью join() получили строковое представление полученной комбинации.

И, как можно заметить, в результате мы получили те самые 27 так называемых слов.

Можно добавить в цикл некий фильтр (условие). Например, сделаю так, чтобы комбинируемые слова начинались только с «X» и заканчивались на «YZY»:

Попробуем сгенерировать всевозможные автомобильные номера для одного региона. Способ, конечно, не особо рациональный, но для примера сгодится:

from itertools import product import re chars = '0123456789АВЕКМНОРСТУХ' reg = '[АВЕКМНОРСТУХ]\d[АВЕКМНОРСТУХ]' for i in product(chars, repeat=6): if re.fullmatch(reg, ''.join(i)): print(''.join(i))

Кстати, если добавить в цикл счётчик, то в итоге получим цифру 1.728.000 (12*10*10*10*12*12). Именно столько номеров формата x000xx можно наклепать для одного региона 🙂

2. Перестановка символов в наборе

В отличие от предыдущего примера, теперь мы не можем использовать по несколько раз один и тот же символ. Можем только переставлять их местами. Принцип подсчёта количества комбинаций остаётся тот же: необходимо перемножить количество вариантов символов на каждую позицию слова между собой. Но поскольку по мере составления слова на каждую последующую позицию символов будет оставаться всё меньше и меньше, то и формула также меняется на: n! / (n-k)! (n — количество доступных символов, k — длина слова) . Если n = k, то можно использовать упрощённую формулу: n! (факториал числа n).

В питоне для таких целей используется функция permutations(). Принимает тоже два параметра: набор символов и длину генерируемой комбинации:

from itertools import permutations for i in permutations('АБВ'): print(''.join(i))

Из трёх букв будет сгенерировано 6 различных слов с неповторяющимися символами (1! = 1 * 2 * 3 = 6)

Попробуем составить трёхзначные слова в 5-символьном алфавите (5! / (5-3)! = 120 / 2 = 60):

Кстати, если в заданном «алфавите» есть повторяющиеся символы, то они будут повторяться и в комбинациях:

3. Сочетания без повторений

А если нужно составить не комбинации, а отдельные неповторяющиеся сочетания? Например, есть 6 человек. Вопрос: какими способами их можно разбить по парам? Опять же, пользуемся формулой: n! / (n-k)! / k! (n — количество доступных объектов/символов, k — количество сочетаний) . Соответственно, существует 6! / (6-2)! / 2! = 720 / 24 / 2 = 15 вариантов разбиения этих 6 персон по парам.

Теперь реализуем эту задачу на питоне с помощью функции combinations(). Принимает она два параметра — список и кол-во сочетаний:

from itertools import combinations for i in combinations(['Юля', 'Даша', 'Соня', 'Дима', 'Игорь', 'Вадим'], 2): print(' - '.join(i))

Результат работы программы будет таков:

На этом, пожалуй, на сегодня всё. С наступающим! 🎉 🎊

  • 5id15
  • 27.12.2022
  • 5 524
  • 0
  • 85

Источник

Комбинаторика в Python

Стандартная библиотека python, начиная с версии 2.2, предоставляет множество средств для генерирования комбинаторных объектов, но в интернете мне не удалось найти ни одной статьи, которая подробно рассказывала бы о работе с ними. Поэтому я решил исправить это упущение.

Начну с того, что расскажу о комбинаторике и ее основных формулах. Если же вы уже знакомы с этим разделом математики — можете пропустить эти абзацы.

Допустим, у нас есть строка, состоящая из n разных букв и мы хотим вычислить все способы переставить эти буквы местами так, чтобы получить новую строку. На первую позицию в строке мы можем выбрать одну из n букв, имеющихся у нас, на вторую позицию одну из n-1-ой буквы и так далее. В итоге получаем произведение n (n-1)… *1 = n! количество перестановок из n элементов без повторений.

Теперь представим, что количество букв в строке ограничено. У нас есть n доступных букв и мы хотим вычислить количество способов составить из них строку длины k, где k < n, каждую букву мы можем использовать лишь единожды. Тогда на первую позицию в строке мы можем поставить одну из n букв, на вторую позицию одну из n-1 буквы и на k-ую позицию одну из n-k+1 буквы. Общее количество строк будет равно n (n — 1) (n — 2) (n — k + 2) (n — k + 1) = n!/(n-k)! количество размещений из n по k. Если же уникальность букв не требуется, то мы получим формулу n. nn = n^k количество размещений из n по k с повторениями.

Рассмотрим случай посложнее, у нас есть n коробок каждая из которых содержит множество конфет одного вкуса, но в разных коробках вкусы разные. Сколько существует способов составить подарок другу из k конфет, при чем один и тот же вкус может встречаться любое количество раз? Так как порядок для нас значения не имеет, давайте разложим подарочные сладости следующим образом: в начале будут лежать последовательно конфеты первого вкуса, затем второго и так далее, а между конфетами разных вкусов положим спички, если конфеты какого-то вкуса отсутствуют в нашем подарке — спички, которые должны были окаймлять этот вкус слева и справа будут стоять рядом. Того у нас получится последовательность, состоящая из k конфет и n-1 спички, ибо вкусов всего n, а спички разделяют их. Теперь заметим, что по расположению спичек, мы можем восстановить исходное множество. Тогда ответом будет количество способов разместить n-1 спичку в n+k-1 ячейку без учета порядка, что равно количеству сочетаний из n+k-1 по n-1, формула: количество сочетаний из n по k с повторениями.

Теперь рассмотрим несколько задач на комбинаторику, чтобы закрепить материал.

Задача 1

Есть 20 человек, сколько существует способов разбить их на пары
Решение: возьмем первого человека, сколько существует способов выбрать ему пару: , возьмем второго человека, сколько существует способов выбрать ему пару: . Ответ: 19. = 654729075

Задача 2

Есть 10 мужчин и 10 девушек, сколько существует способов разбить их на компании, состоящие из одинакового количества и мужчин и девушек, пустая компания не считается
Решение:
Cпособ 1: количество способов собрать компанию из одного мужчины и одной девушки равно произведению количества способов выбрать одну девушку и количества способов выбрать одного мужчину. Количество способов выбрать одну девушку из 10 равно сочетанию из 10 по 1 без повторений, с мужчинами аналогично, поэтому возведем в квадрат. Далее аналогично вычислим сочетания из 10 по 2, из 10 по 3 и так далее до сочетания из 10 по 10. Итоговая формула: .
Способ 2: рассмотрим множество мужчин, входящих в компанию и множество девушек, не входящих в нее. По этому множеству можно однозначно восстановить компанию, а количество людей в нем всегда равно 10, так как , k — количество мужчин в компании, — количество девушек, не вошедших в нее. Количество таких множеств равно количеству сочетаний из 20 по 10, в конечном ответе мы также вычтем единицу, чтобы не учитывать пустую компанию, когда в нашем множестве 10 девушек. Итоговая формула: .

Итак, мы разобрались с теорией, теперь научимся генерировать комбинаторные объекты с помощью стандартной библиотеки python.
Работать мы будем с библиотекой itertools

С помощью функции permutations можно сгенерировать все перестановки для итерируемого объекта.

Пример 1

for i in permutations('abc'): print(i, end=' ') # abc acb bac bca cab cba print() for i in permutations('abb'): print(i, end=' ') # abb abb bab bba bab bba 

Исходя из второго вызова заметим, что одинаковые элементы, стоящие на разных позициях, считаются разными.

Пример 2

for i in permutations('abc', 2): print(i, end=' ') # ab ac ba bc ca cb 

Размещение отличается от перестановки ограничением на количество доступных ячеек

Пример 3

for i in product('abc', repeat=2): print(i, end=' ') # aa ab ac ba bb bc ca cb cc

C помощью размещений с повторениями можно легко перебрать все строки фиксированной длины, состоящие из заданных символов

Пример 4

for i in combinations('abcd', 2): print(i, end=' ') # ab ac ad bc bd cd 

С помощью сочетаний без повторений можно перебрать все наборы не повторяющихся букв из заданной строки, массива или другого итерируемого объекта без учета порядка

Пример 5

for i in combinations_with_replacement('abcd', 2): print(i, end=' ') # aa ab ac ad bb bc bd cc cd dd 

Результат аналогичен вызову combinations, но в результат также добавлены множества с одинаковыми элементами.

Материалы:
Н.В. Горбачев «Сборник олимпиадных задач по математике»
Документация по python на русском

Источник

Читайте также:  Postgresql sqlalchemy python orm
Оцените статью