想象一下3x3网格:
[A, B, %]
[C, %, D]
[E, F, G]
百分比%
代表空格/位置。
行可以像字符串上的珠一样移动,这样第一行的配置的排列可以是以下任何一个:
[A, B, %] or [A, %, B] or [%, A, B]
同样适用于第二行。第三行不包含空插槽,因此无法更改。
考虑到每行可能的排列,我试图生成所有可能的网格。
输出应该产生以下网格:
[A, B, %] [A, B, %] [A, B, %]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
[A, %, B] [A, %, B] [A, %, B]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
[%, A, B] [%, A, B] [%, A, B]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
我尝试了一种查看每一行并左右移动空间,然后生成新网格并递归的方法。我将所有网格保留在一组中,并确保我只生成尚未检查过的位置以防止无限递归。
然而,我的算法似乎非常低效(每个排列约1秒!!)并且看起来也不是很好。我想知道是否有一种雄辩的方式来做到这一点?特别是在python中。
我有一些模糊的想法,但我确信有一种方法可以做到这一点,简短而简单,我忽略了。
编辑: 3x3就是一个例子。网格可以是任何大小,它确实是重要的行组合。例如:
[A, %, C]
[D, E, %, G]
[H, I]
也是一个有效的网格。
编辑2:这些信件必须保持其订单。例如[A, %, B] != [B, %, A]
和[B, A, %]
无效
答案 0 :(得分:2)
首先,你必须为每一行获得所有想要的排列。然后计算所有线的叉积。
通过使用字母[A,B,%]并改变起始索引,可以简单地计算一行的排列:
import itertools
# Example: line = ['A','B','%']
def line_permutations(line):
if '%' not in line:
return [line]
line.remove('%') # use copy.copy if you don't want to modify your matrix here
return (line[:i] + ['%'] + line[i:] for i in range(len(line) + 1))
使用itertools.product
最容易实现交叉产品matrix = [['A','B','%'], ['C', '%', 'D'], ['E', 'F', 'G']]
permutations = itertools.product(*[line_permutations(line) for line in matrix])
for p in permutations:
print(p)
此解决方案在内存和CPU要求方面是最佳的,因为排列永远不会重新计算。
示例输出:
(['%', 'A', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', 'D', '%'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['C', 'D', '%'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', 'D', '%'], ['E', 'F', 'G'])
答案 1 :(得分:1)
定义一个名为cycle
的函数>>> def cycle(lst):
while True:
lst=lst[1:]+lst[0:1] if '%' in lst else lst
yield lst
最终结果如下
>>> for g in list(itertools.product(*[[x for (x,y) in zip(cycle(row),
range(0,len(row) if '%' in row else 1))] for row in grid])):
for r in g:
print r
print "="*10
对于您的网格,这将生成
['B', '%', 'A']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['B', '%', 'A']
['D', 'C', '%']
['E', 'F', 'G']
===============
['B', '%', 'A']
['C', '%', 'D']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['D', 'C', '%']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['C', '%', 'D']
['E', 'F', 'G']
===============
['A', 'B', '%']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['A', 'B', '%']
['D', 'C', '%']
['E', 'F', 'G']
===============
['A', 'B', '%']
['C', '%', 'D']
['E', 'F', 'G']
===============
答案 2 :(得分:0)
天真的实施:
g=[['A', 'B', '%'],
['C', '%', 'D'],
['E', 'F', 'G']]
from collections import deque
from itertools import product
def rotations(it):
d = deque(it,len(it))
for i in xrange(len(it)):
d.rotate(1)
yield list(d)
for i in product(*[rotations(x) if '%' in x else [x] for x in g]):
print i
给出:
(['%', 'A', 'B'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G'])
答案 3 :(得分:0)
在这里。请注意,一方面这种方法不太干净,但它允许您只计算一次#len(matrix [0]) - 1的排列,并将它们用作输出的模板。
from itertools import permutations,product
def charPermutation(matrix):
permutation_list=list(permutations(["%%"]+["%s"]*(len(matrix[0])-1))) #Compute once, use infinitely
perms={i:[] for i in range(len(matrix))}
for it,line in enumerate(matrix):
chars=list(set(line)-set(["%"]))
if sorted(line)==sorted(chars):
perms[it]+=["".join([str(i) for i in line])]
else:
for p in permutation_list:
perms[it]+=["".join(["".join(p) % tuple(chars)])]
perms[it]=list(set(perms[it]))
return product(*[[list(k) for k in i] for i in perms.values()])
g=[
["A", "B", "%"],
["C", "%", "D"],
["E", "F", "G"]]
for x in charPermutation(g):
print [i for i in x]
[['A', '%', 'B'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['A', '%', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['A', '%', 'B'], ['C', '%', 'D'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G']]