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)
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).
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']]
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)]