import itertools as IT
def perm_rev(iterable):
for grp in IT.product(*[[x, -x] for x in iterable]): # 1
for item in IT.permutations(grp): # 2
yield item
For example,
In [46]: list(perm_rev([1,2]))
Out[46]: [(1, 2), (2, 1), (1, -2), (-2, 1), (-1, 2), (2, -1), (-1, -2), (-2, -1)]
For each
x
initerable
,grp
selects eitherx
or-x
. For example,In [53]: list(IT.product([-1,1], [-2,2])) Out[53]: [(-1, -2), (-1, 2), (1, -2), (1, 2)]
- Then for each
grp
, generate the permutions ofgrp
.
Note also that your all_perms
could be written in terms of itertools.permutations:
def all_perms(elements):
return IT.permutations(elements)
The two are essentially the same (except for the order of the elements, and that IT.permutations
returns an iterator instead of a list).
To generalize perm_rev
to apply a function other than reverse
, you could do this:
def reverse(x):
return [x, -x]
def perm_rev(iterable, options):
for grp in IT.product(*[options(x) for x in iterable]):
for item in IT.permutations(grp):
yield item
Then, call perm_rev
like this:
In [58]: list(perm_rev([1,2], reverse))
Out[58]: [(1, 2), (2, 1), (1, -2), (-2, 1), (-1, 2), (2, -1), (-1, -2), (-2, -1)]