Понятно, что самый простой «эффективный» алгоритм можно объяснить следующим образом: сначала сгенерируйте перестановки длины 2. Затем вставьте 3 экземпляра None
всеми возможными способами.
Однако, это более эффективен: во-первых, сгенерируйте все индексы, в которых вы хотите, чтобы ваши два элемента были. Затем для каждого набора индексов для каждой перестановки длины 2 подставляем эти элементы в заданные индексы.
from itertools import combinations, permutations, product
base_list = [None] * 5
values = [0, 1, 2]
all_indices = combinations(range(5), 2)
all_perms = permutations(values, 2)
for (i, j), (x, y) in product(all_indices, all_perms):
list_copy = base_list[:]
list_copy[i] = x
list_copy[j] = y
print(list_copy)
# [0, 1, None, None, None]
# [0, 2, None, None, None]
# ...
# [None, None, None, 2, 0]
# [None, None, None, 2, 1]
Это должно быть легко расширяемым для входов различной длины.
def inserted_permutations(size, values, insert_count, default=None):
base = [default] * size
all_indices = combinations(range(size), insert_count)
all_perms = permutations(values, insert_count)
for indices, values in product(all_indices, all_perms):
base_copy = base[:]
for index, value in zip(indices, values):
base_copy[index] = value
yield base_copy