sympy
также предоставляет все необходимое:
from sympy.utilities.iterables import multiset_permutations
max_at_index = [0, 2, 2, 1, 2, 1, 2, 1, 3, 1]
m_set = {i: n for i, n in enumerate(max_at_index) if n != 0}
for perm in multiset_permutations(m_set, 4):
print(perm)
Объяснение:
тип данных, на котором это основано, является мультимножеством (т.е. набор, в котором элементы могут появляться более одного раза, но порядок не имеет значения).есть функция для такой структуры данных в sympy
: sympy.utilities.iterables.multiset
from itertools import chain
from sympy.utilities.iterables import multiset
max_at_index = [0, 2, 2, 1, 2, 1, 2, 1, 3, 1]
m_set = multiset(chain.from_iterable(n * [i] for i, n in enumerate(max_at_index)))
# {1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 2, 7: 1, 8: 3, 9: 1}
на самом деле multiset
просто возвращает dict
;поэтому это проще:
m_set = {i: n for i, n in enumerate(max_at_index) if n != 0}
# {1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 2, 7: 1, 8: 3, 9: 1}
к счастью sympy
также имеет методы для перестановки и объединения этих мультимножеств без генерации повторений:
from sympy.utilities.iterables import multiset_permutations
for perm in multiset_permutations(m_set, 4):
print(perm)
Чтобы помочь с распараллеливанием, сначала может помочь расчет комбинаций:
from sympy.utilities.iterables import multiset_combinations, multiset_permutations
for comb in multiset_combinations(m_set, 4):
print()
for perm in multiset_permutations(comb):
print(perm)
, который производит (добавляет пробел после каждой новой комбинации)
[1, 1, 2, 2]
[1, 2, 1, 2]
[1, 2, 2, 1]
[2, 1, 1, 2]
[2, 1, 2, 1]
[2, 2, 1, 1]
[1, 1, 2, 3]
[1, 1, 3, 2]
[1, 2, 1, 3]
[1, 2, 3, 1]
[1, 3, 1, 2]
[1, 3, 2, 1]
[2, 1, 1, 3]
[2, 1, 3, 1]
[2, 3, 1, 1]
[3, 1, 1, 2]
[3, 1, 2, 1]
[3, 2, 1, 1]
...
[8, 8, 8, 9]
[8, 8, 9, 8]
[8, 9, 8, 8]
[9, 8, 8, 8]