简体   繁体   中英

Generating permutations of a unique sequence of positive and negative integers

I have a sequence of numbers:

[12,10,6,4,2]

Each of those numbers can be either positive or negative.

This tells us that there are 2^5 = 32 possible ways we can arrange the + or - signs for any given sequence of 5 numbers.

How do I generate all the possible sequences of + or - for while keeping the order of these numbers intact?

CODE:

combs = itertools.permutations('+++++-----', 5)
combs = list(combs)

values = [12,10,6,4,2]

broadcasted = [tuple(zip(i,values)) for i in combs]

test = set()

for item in broadcasted:
    test.add(item)

print(len(test))
print(test)

OUTPUT:


32


{(('+', 12), ('+', 10), ('-', 6), ('+', 4), ('+', 2)),
 (('+', 12), ('+', 10), ('+', 6), ('-', 4), ('+', 2)), 
 (('+', 12), ('+', 10), ('+', 6), ('+', 4), ('+', 2)), 
 (('+', 12), ('+', 10), ('-', 6), ('-', 4), ('+', 2)), 
 (('-', 12), ('+', 10), ('+', 6), ('+', 4), ('-', 2)), 
 (('-', 12), ('+', 10), ('-', 6), ('-', 4), ('-', 2)), 
 (('+', 12), ('+', 10), ('+', 6), ('-', 4), ('-', 2)), 
 (('+', 12), ('+', 10), ('-', 6), ('+', 4), ('-', 2)), 
 (('-', 12), ('+', 10), ('+', 6), ('-', 4), ('-', 2)), 
 (('-', 12), ('+', 10), ('-', 6), ('+', 4), ('-', 2)), 
 (('+', 12), ('-', 10), ('+', 6), ('-', 4), ('+', 2)), 
 (('-', 12), ('+', 10), ('+', 6), ('-', 4), ('+', 2)), 
 (('-', 12), ('+', 10), ('-', 6), ('+', 4), ('+', 2)), 
 (('-', 12), ('-', 10), ('+', 6), ('+', 4), ('-', 2)), 
 (('-', 12), ('-', 10), ('-', 6), ('-', 4), ('-', 2)), 
 (('+', 12), ('-', 10), ('+', 6), ('+', 4), ('-', 2)), 
 (('-', 12), ('-', 10), ('+', 6), ('-', 4), ('+', 2)), 
 (('-', 12), ('-', 10), ('-', 6), ('+', 4), ('+', 2)), 
 (('-', 12), ('-', 10), ('+', 6), ('+', 4), ('+', 2)), 
 (('-', 12), ('-', 10), ('-', 6), ('-', 4), ('+', 2)), 
 (('+', 12), ('-', 10), ('-', 6), ('+', 4), ('-', 2)), 
 (('+', 12), ('-', 10), ('+', 6), ('-', 4), ('-', 2)),  
 (('-', 12), ('-', 10), ('+', 6), ('-', 4), ('-', 2)), 
 (('-', 12), ('-', 10), ('-', 6), ('+', 4), ('-', 2)), 
 (('+', 12), ('+', 10), ('+', 6), ('+', 4), ('-', 2)), 
 (('+', 12), ('+', 10), ('-', 6), ('-', 4), ('-', 2)), 
 (('-', 12), ('+', 10), ('+', 6), ('+', 4), ('+', 2)), 
 (('-', 12), ('+', 10), ('-', 6), ('-', 4), ('+', 2)), 
 (('+', 12), ('-', 10), ('+', 6), ('+', 4), ('+', 2)), 
 (('+', 12), ('-', 10), ('-', 6), ('-', 4), ('+', 2)), 
 (('+', 12), ('-', 10), ('-', 6), ('+', 4), ('+', 2)), 
 (('+', 12), ('-', 10), ('-', 6), ('-', 4), ('-', 2))}

While it works to take a sequence of all options (that is 5 '+'s and 5 '-'s), permute them in sequences of 5, broadcast them to the given digits and boil down in a set, it's way too computationally intensive for a sequence of 10 which would require us to construct over 3 million permutations. How can I do this faster?

You don't need permutations for this; the sequences of signs are the elements of the Cartesian product of five copies of ['+', '-'] .

>>> values = [12, 10, 6, 4, 2]
>>> from itertools import product
>>> for signs in product('+-', repeat=5):
...     t = tuple(zip(signs, values))
...     print(t)
... 
(('+', 12), ('+', 10), ('+', 6), ('+', 4), ('+', 2))
(('+', 12), ('+', 10), ('+', 6), ('+', 4), ('-', 2))
(('+', 12), ('+', 10), ('+', 6), ('-', 4), ('+', 2))
(('+', 12), ('+', 10), ('+', 6), ('-', 4), ('-', 2))
(('+', 12), ('+', 10), ('-', 6), ('+', 4), ('+', 2))
(('+', 12), ('+', 10), ('-', 6), ('+', 4), ('-', 2))
(('+', 12), ('+', 10), ('-', 6), ('-', 4), ('+', 2))
(('+', 12), ('+', 10), ('-', 6), ('-', 4), ('-', 2))
(('+', 12), ('-', 10), ('+', 6), ('+', 4), ('+', 2))
(('+', 12), ('-', 10), ('+', 6), ('+', 4), ('-', 2))
(('+', 12), ('-', 10), ('+', 6), ('-', 4), ('+', 2))
(('+', 12), ('-', 10), ('+', 6), ('-', 4), ('-', 2))
(('+', 12), ('-', 10), ('-', 6), ('+', 4), ('+', 2))
(('+', 12), ('-', 10), ('-', 6), ('+', 4), ('-', 2))
(('+', 12), ('-', 10), ('-', 6), ('-', 4), ('+', 2))
(('+', 12), ('-', 10), ('-', 6), ('-', 4), ('-', 2))
(('-', 12), ('+', 10), ('+', 6), ('+', 4), ('+', 2))
(('-', 12), ('+', 10), ('+', 6), ('+', 4), ('-', 2))
(('-', 12), ('+', 10), ('+', 6), ('-', 4), ('+', 2))
(('-', 12), ('+', 10), ('+', 6), ('-', 4), ('-', 2))
(('-', 12), ('+', 10), ('-', 6), ('+', 4), ('+', 2))
(('-', 12), ('+', 10), ('-', 6), ('+', 4), ('-', 2))
(('-', 12), ('+', 10), ('-', 6), ('-', 4), ('+', 2))
(('-', 12), ('+', 10), ('-', 6), ('-', 4), ('-', 2))
(('-', 12), ('-', 10), ('+', 6), ('+', 4), ('+', 2))
(('-', 12), ('-', 10), ('+', 6), ('+', 4), ('-', 2))
(('-', 12), ('-', 10), ('+', 6), ('-', 4), ('+', 2))
(('-', 12), ('-', 10), ('+', 6), ('-', 4), ('-', 2))
(('-', 12), ('-', 10), ('-', 6), ('+', 4), ('+', 2))
(('-', 12), ('-', 10), ('-', 6), ('+', 4), ('-', 2))
(('-', 12), ('-', 10), ('-', 6), ('-', 4), ('+', 2))
(('-', 12), ('-', 10), ('-', 6), ('-', 4), ('-', 2))

For a sequence of size 10, the Cartesian product will have 2 10 = 1,024 elements, which is perfectly feasible.

I'm gonna gamble on this result format being easier to use (if not for you, then maybe for someone else).

>>> for t in product(*((x, -x) for x in values)):
        print(t)

(12, 10, 6, 4, 2)
(12, 10, 6, 4, -2)
(12, 10, 6, -4, 2)
(12, 10, 6, -4, -2)
(12, 10, -6, 4, 2)
(12, 10, -6, 4, -2)
...
(-12, -10, -6, -4, -2)

For example, you can easily use it to compute all possible sums:

>>> set(map(sum, product(*((x, -x) for x in values))))
{34, 2, -6, -30, 6, -26, 10, -22, 14, -18, 18, -14, -34, 22, -2, -10, 26, 30}

As kaya3 commented, you can even use {x, -x} so that x=0 leads to {0} . Every zero in the input then halves the number of output tuples.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM