我对Python特别感兴趣,但也非常感谢通用解决方案。我有一个偶数个节点(对于一个特定的例子,让我们说12个):
[' a1',' a2',' a3',' b1',' b2',& #39; b3',' c1',' c2',' c3',' d1',' d2&# 39;,' d3']
每个节点必须连接到另一个节点,形成6个连接(对)。
我需要找到一种方法来找到所有可能的连接组合。
此外,'a1'-'a2'
应被视为与'a2'-'a1'
一些想法:
我可以获取可能itertools.combinations(lst, 2)
的列表,但节点不可重用。比如,连接'a1'<->'a2'
应该从'a1'<->'a3'
已使用的可用选项中删除'a1'
。
我不知道搜索是否适用,因为似乎存在一些问题:
答案 0 :(得分:3)
这是针对您的问题的递归解决方案:
def findPairs(l):
# recursion anchor, basic case:
# when we have 2 nodes only one pair is possible
if len(l) == 2:
yield [tuple(l)]
else:
# Pair the first node with all the others
for i in range(1, len(l)):
# Current pair
pair1 = [(l[0], l[i])]
# Combine it with all pairs among the remaining nodes
remaining = l[1:i] + l[i+1:]
for otherPairs in findPairs(remaining):
yield pair1 + otherPairs
可以相应地计算所有解决方案的数量:
def N(n):
if n == 2:
return 1
return (n-1) * N(n-2)
请注意,我没有检查n % 2 == 0
。
同样对于n==len(l)==12
,您将获得10395种可能的组合,这是非常可行的。但是这段代码虽然简短易读,却一遍又一遍地生成和重新生成列表和元组,这使得它变慢。
看看它是否足够快,否则我们将不得不调整它。
答案 1 :(得分:1)
我认为你只需要使用排列和take adjacent pairs 删除任何反向订单重复:
nodes = 'A1 A2 B1 B2 C1 C2'.split()
perms = set()
for perm in itertools.permutations(nodes):
p = tuple(sorted(
[tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)]))
perms.add(p)
for perm in sorted(perms):
print(perm)
那么这是如何运作的呢?
我们需要循环遍历节点的每个排列:
for perm in itertools.permutations(nodes):
然后在排列中从相邻节点创建对:
[tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)]
这是通过获取两个相邻节点并对它们进行排序来完成的 可以在以后寻找傻瓜:
tuple(sorted(perm[i:i + 2]))
然后创建tuple
,以便我们允许immutable
索引。然后将所有对进行一次排列并执行相同的操作
sort
并转换为tuple
整个排列:
p = tuple(sorted(
[tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)]))
然后将排列添加到set
,这会删除重复项:
perms.add(p)
打印结果:
for perm in sorted(perms):
print(perm)