Getting all the combinations of a Numpy Array - python

If I have a Numpy array like X=np.array([1,2,3,4,5])
I want to put all of the combinations of these numbers into an array.
How would I go about getting an array with each row being a combination of X and the length is how ever many combinations there are?

Assuming from your question you are actually looking for permutations:
from itertools import permutations
import numpy as np
x = np.array([1, 2, 3, 4, 5])
perm_array = np.asarray([p for p in permutations(x)])
print(perm_array.shape)
# prints(120, 5)
Each row of perm_array will contain a permutation of your input.
Watch out that the number of permutations grows extremely quickly!

Available in itertools:
from itertools import combinations
X=np.array([1,2,3,4,5])
X_combinations = {} # dictionary key r: combinations of rank r.
for r in range(len(X) + 1):
X_combinations[r] = list(combinations(X, r))
from pprint import pprint
pprint(X_combinations)
output:
{0: [()],
1: [(1,), (2,), (3,), (4,), (5,)],
2: [(1, 2),
(1, 3),
(1, 4),
(1, 5),
(2, 3),
(2, 4),
(2, 5),
(3, 4),
(3, 5),
(4, 5)],
3: [(1, 2, 3),
(1, 2, 4),
(1, 2, 5),
(1, 3, 4),
(1, 3, 5),
(1, 4, 5),
(2, 3, 4),
(2, 3, 5),
(2, 4, 5),
(3, 4, 5)],
4: [(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)],
5: [(1, 2, 3, 4, 5)]}

Related

Summing over functions between lists

Working in Python.
Take k and n positive integers.
I have a function F with input a list L of positive integers where len(L) = k, max(L) < n+1. F returns an integer.
I want to return sum([F(L) for L a list of positive integers with len(L) = k, max(L)<n+1])
The naive approach is to have k nested for loops.
value = 0
for jj1 in range(1,n+1):
for jj2 in range(1,n+1):
...
for jjk in range(1,n+1)
value = value + F([jj1,jj2,...,jjk])
return value
This is not satisfactory because I want to take this sum in a loop over various values of k (so sometimes k =1, sometimes k=10).
I'm hoping there is some standard trick to do this?
You want itertools.product.
>>> from itertools import product
>>> n, k = 4, 3
>>> list(product(range(1, n+1), repeat=k))
[(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4), (1, 4, 1), (1, 4, 2), (1, 4, 3), (1, 4, 4), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4), (2, 4, 1), (2, 4, 2), (2, 4, 3), (2, 4, 4), (3, 1, 1), (3, 1, 2), (3, 1, 3), (3, 1, 4), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 1), (3, 3, 2), (3, 3, 3), (3, 3, 4), (3, 4, 1), (3, 4, 2), (3, 4, 3), (3, 4, 4), (4, 1, 1), (4, 1, 2), (4, 1, 3), (4, 1, 4), (4, 2, 1), (4, 2, 2), (4, 2, 3), (4, 2, 4), (4, 3, 1), (4, 3, 2), (4, 3, 3), (4, 3, 4), (4, 4, 1), (4, 4, 2), (4, 4, 3), (4, 4, 4)]
Given F, n, and k, you can therefore do:
sum(F(list(L)) for L in product(range(1, n+1), repeat=k))
(or leave off the list call if it's fine for L to be a tuple instead of a list)

Finding all possible permutations of an unfixed length of numbers to reach a given sum or product

Using plain Python or any Python libraries, how would you go about finding all possible combinations of elements in a list l that equal a given value val using addition, subtraction, or multiplication? Assume the length of the list isn't always the same, assume each element in the list can only be used once in each combination, and assume there isn't any use of parentheses.
For example:
We're given a list of numbers: l = [1,2,3,4]
We're given a value equaling the combination of values: val = 6
The output would include the following:
[2,4], since 2+4=6
And [4,2], since 4+2=6
And [1,3,2], since 1+3+2=6
And [1,2,4], since 1*2+4=6
etc.
I've tried using itertools.permutations:
>>> from itertools import permutations
>>> l = [1,2,3,4]
>>> val = 6
>>> correct_combos = []
>>> for i in range(1, len(l)+1):
... for p in permutations(l, r=i):
... if sum(p) == val:
... correct_combos.append(p)
I'm able to only implement the code for testing the sum of all combinations of elements in the list.
>>> print(correct_combos)
[(2, 4), (4, 2)]
I'm stuck on finding permutations of elements in the list using a combination of addition, subtraction, and multiplication.
I don't know if this algorithm is efficient, but it works fine:
from itertools import permutations, product
l = [1,2,3,4]
val = 6
operator = ['+', '-', '*']
correct_combos=[]
for r in range(1, len(l)+1):
for item in permutations(l,r):
for unit in product(operator, repeat=r-1):
res=""
for idx in range(0,r-1):
res+=str(item[idx])+unit[idx]
res+=str(item[-1])
if(val==eval(res)):
if item not in correct_combos:
correct_combos.append(item)
print(correct_combos)
Output
[(2, 3), (2, 4), (3, 2), (4, 2), (1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 4, 2), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 4, 1), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 4, 1), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 3, 1), (1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
Non recursive solution:
from itertools import permutations, product, accumulate
from collections import deque
from operator import add, sub, mul
l = [1, 2, 3, 4]
val = 6
correct_combos = []
def is_correct(p, val, ops=[add, sub, mul]):
if len(p) == 1:
return p[0] == val
for op in product(ops, repeat=len(p) - 1):
iop = iter(op)
l = deque(accumulate(p, lambda a, b: next(iop)(a, b)), maxlen=1)[0]
if l == val:
return True
return False
for i in range(1, len(l) + 1):
for p in permutations(l, r=i):
if is_correct(p, val):
correct_combos.append(p)
print(correct_combos)
Prints:
[(2, 3), (2, 4), (3, 2), (4, 2), (1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 4, 2), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 4, 1), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 4, 1), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 2, 3), (4, 3, 1), (1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
You can use a recursive generator function:
from operator import add, sub, mul
l = [1,2,3,4]
val = 6
def combos(c = [], r_exp = None):
if r_exp == val:
yield c
else:
for i in filter(lambda x:x not in c, l):
if not c:
yield from combos(c=[i], r_exp = i)
else:
for s, f in [['+', add], ['-', sub], ['*', mul]]:
yield from combos(c=c+[s, i], r_exp = f(r_exp, i))
print([''.join(map(str, i)) for i in combos()])
Output:
['1+2+3', '1-2+3+4', '1-2+4+3', '1*2*3', '1*2+4', '1+3+2', '1+3-2+4', '1+3+4-2', '1*3*2', '1+4-2+3', '1+4+3-2', '1*4+2', '1*4-2*3', '2+1+3', '2*1*3', '2*1+4', '2+3+1', '2*3', '2+4', '2*4+1-3', '2*4-3+1', '3+1+2', '3+1-2+4', '3+1+4-2', '3-1+4', '3-1*4-2', '3*1*2', '3+2+1', '3-2+1+4', '3-2+4+1', '3*2', '3+4+1-2', '3+4-1', '3+4-2+1', '4+1-2+3', '4+1+3-2', '4-1*2', '4-1+3', '4*1+2', '4*1-2*3', '4+2', '4-2+1+3', '4-2*1*3', '4-2+3+1', '4-2*3', '4*2+1-3', '4*2-3+1', '4+3+1-2', '4+3-1', '4+3-2+1']
To just get the tuple results, only a small change needs to be made:
for f in [add, sub, mull]:
yield from combos(c=c+[i], r_exp = f(r_exp, i))
...
print(list(map(tuple, combos())))
Output:
[(1, 2, 3), (1, 2, 3, 4), (1, 2, 4, 3), (1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 2, 4), (1, 3, 4, 2), (1, 3, 2), (1, 4, 2, 3), (1, 4, 3, 2), (1, 4, 2), (1, 4, 2, 3), (2, 1, 3), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 3), (2, 4), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2), (3, 1, 2, 4), (3, 1, 4, 2), (3, 1, 4), (3, 1, 4, 2), (3, 1, 2), (3, 2, 1), (3, 2, 1, 4), (3, 2, 4, 1), (3, 2), (3, 4, 1, 2), (3, 4, 1), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 1, 2), (4, 1, 3), (4, 1, 2), (4, 1, 2, 3), (4, 2), (4, 2, 1, 3), (4, 2, 1, 3), (4, 2, 3, 1), (4, 2, 3), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 1), (4, 3, 2, 1)]
from itertools import chain, combinations
def subSet(l):
return chain.from_iterable(combinations(l, r) for r in range(len(l) + 1))
def whatWeWant(l, val):
x = 0
for i in l:
x += i
if x == val:
return True
return False
l = [1, 2, 3, 4]
val = 6
allSubSets = list(subSet(l))
ans = []
for subSet in allSubSets:
if whatWeWant(subSet, val):
ans.append(subSet)
With this code you can find what you want but you have to specifically say the possible combinations(in whatWeWant method).

Merge list of list with duplicates

Input list
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
And the result should be like:
[(1, 0, 3), ['21:40:44', '21:43:37', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']
The goal is to reduce the duplicates, the unique elements in a column should be stored in a list.
How about using zip. It will merge the 3 list and give you output with duplicates. later use set to remove duplicates. and since you don not want list of tuple for single element only, use list(set(x))[0] if len(set(x))==1 else list(set(x))
a=[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
b=[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
c=[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
l=[list(set(x))[0] if len(set(x))==1 else list(set(x)) for x in list(zip(a,b,c))]
print(l)
>>>[(1, 0, 3), ['21:45:27', '21:40:44', '21:43:37'], (1, 3, 9), (1, 4, 6), ['.060', '.273', '.410']]
the simplest way is this:
in_data = [
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273'],
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060'],
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
]
res = []
for i in range(len(in_data[0])):
data = list(set([x[i] for x in in_data ]))
data = data[0] if len(data) == 1 else data
res.append(data)
print(res)
>>> [(1, 0, 3), ['21:43:37', '21:40:44', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']]

How to generate dynamically combinations of list in python

I want to generate combination dynamically in python, I have a var sessionperweeks (between 2 and 6)
if sessionperweeks==2
for i in range(0,7):
for j in range(i+1,7):
combins.append([i,j])
if sessionperweeks==3
for i in range(0,7):
for j in range(i+1,7):
for k in range(j+1,7):
combins.append([i,j,k])
and so on
Here you go, using combinations from itertools to pick sessions per week from 0-6:
from itertools import combinations
sessionsperweek = int(input("Enter sessions per week:"))
combins = list(combinations(range(7), sessionsperweek))
print("Your possible combinations are:")
print(combins)
Example run with 2 (since OP updated):
Enter sessions per week:2
Your possible combinations are:
[(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6), (4, 5), (4, 6), (5, 6)]
Example run:
Enter sessions per week:6
Your possible combinations are:
[(0, 1, 2, 3, 4, 5), (0, 1, 2, 3, 4, 6), (0, 1, 2, 3, 5, 6), (0, 1, 2, 4, 5, 6), (0, 1, 3, 4, 5, 6), (0, 2, 3, 4, 5, 6), (1, 2, 3, 4, 5, 6)]

python itertools product with steps

Currently, I have a NumPy array:
a = np.array([[1,2],[3,4],[5,6]])
And I am doing the product operation in itertools, but I want to add a step function.
For example:
[ x for x in itertools.product(*a) ]
Result in:
[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]
For the target output with step (1,1,2):
[(1, 3, 5), (1, 4, 5), (2, 3, 5), (2, 4, 5)]
I can't figure it out, here is the problem.
Just use a list slice:
In [578]: import itertools
In [579]: a=[[1,2],[3,4],[5,6]]
In [580]: list(itertools.product(*a))[::2]
Out[580]: [(1, 3, 5), (1, 4, 5), (2, 3, 5), (2, 4, 5)]
There may be a itertools tools to do this as well.
In [586]: list(itertools.islice(itertools.product(*a), None, None,2))
Out[586]: [(1, 3, 5), (1, 4, 5), (2, 3, 5), (2, 4, 5)]
This should do:
step = (1,1,2)
[ x for x in itertools.product(*[a[i,::s] for i,s in enumerate(step)])]
You can use this code. I think your problem is solve.
import itertools
print(list(itertools.product(*[[1,2],[3,4],[5,6]]))[::2])

Categories