Было просто интересно, каков наиболее эффективный способ генерации всех циклических сдвигов списка в Python.В любом направлении.Например, учитывая список [1, 2, 3, 4]
, я хочу сгенерировать либо:
[[1, 2, 3, 4],
[4, 1, 2, 3],
[3, 4, 1, 2],
[2, 3, 4, 1]]
, где следующая перестановка генерируется путем перемещения последнего элемента вперед, либо:
[[1, 2, 3, 4],
[2, 3, 4, 1],
[3, 4, 1, 2],
[4, 1, 2, 3]]
где следующая перестановка генерируется путем перемещения первого элемента назад.
Второй случай немного более интересен для меня, поскольку он приводит к уменьшенному латинскому квадрату (первый случай также дает латинский квадрат, простоне сокращается), что я и пытаюсь использовать для экспериментального проектирования блоков.На самом деле это не сильно отличается от первого случая, поскольку они просто переупорядочивают друг друга, но порядок все равно имеет значение.
Текущая реализация, которую я имею для первого случая:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = [tmplist.pop()] + tmplist
return latin_square
Для второго случая это:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = tmplist[1:] + [tmplist[0]]
return latin_square
Первый случай кажется мне достаточно эффективным, поскольку он использует pop()
, но вы не можете сделать это во второмслучай, поэтому я хотел бы услышать идеи о том, как сделать это более эффективно.Может быть, в itertools
есть что-то, что поможет?Или, может быть, двусторонняя очередь для второго случая?