Просто интересно, какой самый эффективный способ создания всех циклических сдвигов списка в 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
есть что-то, что поможет? Или, может быть, двусторонняя очередь для второго случая?