Я хотел бы иметь возможность принимать ряд чисел и возвращать список, содержащий тройки без дубликатов. Каждый элемент x должен появляться один раз в каждой позиции троек. Цель состоит в том, чтобы получить следующее:
get_combinations_without_duplicates(3) = [(0, 1, 2), (1, 2, 0), (2, 0, 1)]
Для диапазона (3) это просто вращение списка, но для более высоких диапазонов возможны более возможные комбинации. Я хотел бы иметь возможность случайным образом генерировать список троек, удовлетворяющих этим ограничениям.
Предположим, что мы начнем с указания первого элемента каждой тройки для случая, когда n = 4:
[(0,), (1,), (2,), (3,)]
Второй элемент первой тройки может быть любым, кроме 0. После выбора одного из них это ограничивает параметры для следующей тройки и т.д. Цель состоит в том, чтобы иметь функцию, которая принимает число и создает тройки таким образом, но не всегда создает один и тот же набор троек. То есть конечным результатом может быть поворот:
[(0, 1, 2), (1, 2, 3), (2, 3, 0), (3, 0, 1),]
или
[(0, 2, 3), (1, 3, 0), (2, 0, 1), (3, 1, 2)]
Вот реализация этой функции:
def get_combinations_without_duplicates(n):
output = []
second = range(n)
third = range(n)
for i in range(n):
triple = [i]
#Get the second value of the triple, but make sure that it isn't a
#duplicate of the first value
#in the triple or any value that has appeared in the second position of any triple
choices_for_second = [number for number in second if number not in triple]
#Randomly select a number from the allowed possibilities
n_second = random.choice(choices_for_second)
#Append it to the triple
triple.append(n_second)
#Remove that value from second so that it won't be chosen for other triples
second = [number for number in second if number != n_second]
#Do the same for the third value
choices_for_third = [number for number in third if number not in triple]
n_third = random.choice(choices_for_third)
triple.append(n_third)
third = [number for number in third if number != n_third]
output.append(tuple(triple))
return output
Как указано ниже, этот процесс иногда случайно выбирает комбинации, которые не работают. Это можно обработать, если вы выполните что-то вроде:
def keep_trying(n):
try:
return get_combinations_without_duplicates(n)
except IndexError:
return keep_trying(n)
Однако мне интересно, есть ли лучший способ сделать это в целом.