Reputation: 4828
Question: How do I implement double_permutations(s)
below?
>>> s = [('a', 'b'), ('c', 'd'), ('e', 'f')]
>>> for answer in double_permutation(s):
... print(answer) # in some order
[('a', 'b'), ('c', 'd'), ('e', 'f')]
[('a', 'b'), ('d', 'c'), ('e', 'f')]
[('a', 'b'), ('c', 'd'), ('f', 'e')]
[('a', 'b'), ('d', 'c'), ('f', 'e')]
[('a', 'b'), ('e', 'f'), ('c', 'd')]
[('a', 'b'), ('f', 'e'), ('c', 'd')]
[('a', 'b'), ('e', 'f'), ('d', 'c')]
[('a', 'b'), ('f', 'e'), ('d', 'c')]
What I've tried (breaks down once the outer list is longer than 3 elements)
from itertools import permutations
def double_permutation(l):
def double_permutation_recur(s, r):
if not r:
yield s
else:
for permutation in permutations(r):
s1 = s + [permutation[0]]
s2 = s + [(permutation[0][1], permutation[0][0])]
for perm1 in double_permutation_recur(s1, permutation[1:]):
yield perm1
for perm2 in double_permutation_recur(s2, permutation[1:]):
yield perm2
return double_permutation_recur([l[0]], l[1:])
This should yield double_factorial(n-1)
answers for a list of length n
. This works up through n = 3
, but breaks down at n = 4
(which yields 96
instead of 48
answers).
Upvotes: 1
Views: 353
Reputation: 97591
You can build this up from the primitives in the itertools
module
import itertools
s = [('a', 'b'), ('c', 'd'), ('e', 'f')]
Is this what you're describing?
def permute(it):
return itertools.product(*(itertools.permutations(i) for i in it))
>>> for i in permute(s):
... print i
(('a', 'b'), ('c', 'd'), ('e', 'f'))
(('a', 'b'), ('c', 'd'), ('f', 'e'))
(('a', 'b'), ('d', 'c'), ('e', 'f'))
(('a', 'b'), ('d', 'c'), ('f', 'e'))
(('b', 'a'), ('c', 'd'), ('e', 'f'))
(('b', 'a'), ('c', 'd'), ('f', 'e'))
(('b', 'a'), ('d', 'c'), ('e', 'f'))
(('b', 'a'), ('d', 'c'), ('f', 'e'))
Or do you want:
def permute2(it):
return itertools.chain.from_iterable(
permute(p)
for p in itertools.permutations(it)
)
>>> for i in permute2(s):
... print i
(('a', 'b'), ('c', 'd'), ('e', 'f'))
(('a', 'b'), ('c', 'd'), ('f', 'e'))
(('a', 'b'), ('d', 'c'), ('e', 'f'))
(('a', 'b'), ('d', 'c'), ('f', 'e'))
(('b', 'a'), ('c', 'd'), ('e', 'f'))
(('b', 'a'), ('c', 'd'), ('f', 'e'))
(('b', 'a'), ('d', 'c'), ('e', 'f'))
(('b', 'a'), ('d', 'c'), ('f', 'e'))
(('a', 'b'), ('e', 'f'), ('c', 'd'))
(('a', 'b'), ('e', 'f'), ('d', 'c'))
(('a', 'b'), ('f', 'e'), ('c', 'd'))
(('a', 'b'), ('f', 'e'), ('d', 'c'))
(('b', 'a'), ('e', 'f'), ('c', 'd'))
(('b', 'a'), ('e', 'f'), ('d', 'c'))
(('b', 'a'), ('f', 'e'), ('c', 'd'))
(('b', 'a'), ('f', 'e'), ('d', 'c'))
(('c', 'd'), ('a', 'b'), ('e', 'f'))
(('c', 'd'), ('a', 'b'), ('f', 'e'))
(('c', 'd'), ('b', 'a'), ('e', 'f'))
(('c', 'd'), ('b', 'a'), ('f', 'e'))
(('d', 'c'), ('a', 'b'), ('e', 'f'))
(('d', 'c'), ('a', 'b'), ('f', 'e'))
(('d', 'c'), ('b', 'a'), ('e', 'f'))
(('d', 'c'), ('b', 'a'), ('f', 'e'))
(('c', 'd'), ('e', 'f'), ('a', 'b'))
(('c', 'd'), ('e', 'f'), ('b', 'a'))
(('c', 'd'), ('f', 'e'), ('a', 'b'))
(('c', 'd'), ('f', 'e'), ('b', 'a'))
(('d', 'c'), ('e', 'f'), ('a', 'b'))
(('d', 'c'), ('e', 'f'), ('b', 'a'))
(('d', 'c'), ('f', 'e'), ('a', 'b'))
(('d', 'c'), ('f', 'e'), ('b', 'a'))
(('e', 'f'), ('a', 'b'), ('c', 'd'))
(('e', 'f'), ('a', 'b'), ('d', 'c'))
(('e', 'f'), ('b', 'a'), ('c', 'd'))
(('e', 'f'), ('b', 'a'), ('d', 'c'))
(('f', 'e'), ('a', 'b'), ('c', 'd'))
(('f', 'e'), ('a', 'b'), ('d', 'c'))
(('f', 'e'), ('b', 'a'), ('c', 'd'))
(('f', 'e'), ('b', 'a'), ('d', 'c'))
(('e', 'f'), ('c', 'd'), ('a', 'b'))
(('e', 'f'), ('c', 'd'), ('b', 'a'))
(('e', 'f'), ('d', 'c'), ('a', 'b'))
(('e', 'f'), ('d', 'c'), ('b', 'a'))
(('f', 'e'), ('c', 'd'), ('a', 'b'))
(('f', 'e'), ('c', 'd'), ('b', 'a'))
(('f', 'e'), ('d', 'c'), ('a', 'b'))
(('f', 'e'), ('d', 'c'), ('b', 'a'))
Or to "anchor" the first element:
def permute3(s):
return s[:1] + list(p) for p in permute2(s[1:])
>>> for i in permute3(s):
... print i
[('a', 'b'), ('c', 'd'), ('e', 'f')]
[('a', 'b'), ('c', 'd'), ('f', 'e')]
[('a', 'b'), ('d', 'c'), ('e', 'f')]
[('a', 'b'), ('d', 'c'), ('f', 'e')]
[('a', 'b'), ('e', 'f'), ('c', 'd')]
[('a', 'b'), ('e', 'f'), ('d', 'c')]
[('a', 'b'), ('f', 'e'), ('c', 'd')]
[('a', 'b'), ('f', 'e'), ('d', 'c')]
Upvotes: 3