在Python中生成循环置换/减少的拉丁方块
只是想知道在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
可能会有帮助吗? 或者可能是第二种情况的双端队列?
对于第一部分,最简洁的方式可能是
a = [1, 2, 3, 4]
n = len(a)
[[a[i - j] for i in range(n)] for j in range(n)]
# [[1, 2, 3, 4], [4, 1, 2, 3], [3, 4, 1, 2], [2, 3, 4, 1]]
和第二部分
[[a[i - j] for i in range(n)] for j in range(n, 0, -1)]
# [[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]
这些也应该比你的代码更有效率,尽管我没有做任何时间安排。
你可以使用collections.deque:
from collections import deque
g = deque([1, 2, 3, 4])
for i in range(len(g)):
print list(g) #or do anything with permutation
g.rotate(1) #for right rotation
#or g.rotate(-1) for left rotation
它打印:
[1, 2, 3, 4]
[4, 1, 2, 3]
[3, 4, 1, 2]
[2, 3, 4, 1]
要将它改为左旋,只需用g.rotate(-1)
替换g.rotate(1)
g.rotate(-1)
。
切片“保守法则” a = a[:i] + a[i:]
变化a = a[:i] + a[i:]
ns = list(range(5))
ns
Out[34]: [0, 1, 2, 3, 4]
[ns[i:] + ns[:i] for i in range(len(ns))]
Out[36]:
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 0],
[2, 3, 4, 0, 1],
[3, 4, 0, 1, 2],
[4, 0, 1, 2, 3]]
[ns[-i:] + ns[:-i] for i in range(len(ns))]
Out[38]:
[[0, 1, 2, 3, 4],
[4, 0, 1, 2, 3],
[3, 4, 0, 1, 2],
[2, 3, 4, 0, 1],
[1, 2, 3, 4, 0]]
链接地址: http://www.djcxy.com/p/24315.html
上一篇: Generating cyclic permutations / reduced Latin Squares in Python