I am trying to get the subset of list_a with the highest summation of both lists b and c that are below or equal to the threshold. (List b and list c corresponds to list a)
For example
list_a = [1, 2, 3, 4, 5]
list_b = [3,4,7,8,2]
list_c = [4,6,1,5,8]
Threshold = 12
In descending order, I want to obtain a list with all the possible subsets of list_a that, for both lists b and c has a total value less than or equal to the threshold. So, list b has to be lower or equal to the threshold, and list c has to be lower or equal to the threshold. I don't know how I can obtain this with the least amount of calculation time.
With the following function, I am trying to make subsets. Eventually, I want to obtain a list with only those subsets for which the total of list b and list c is below the threshold.
for example subset (1,2,) has 7 as value for list b (3+4) and list c has a value of 10 (4+6).
I tried the following for making the subsets:
def powerset(s):
if s:
tail1 = s[1:]
for e in chain.from_iterable(combinations(tail1, r) for r in range(len(tail1) + 1, -1, -1)):
yield (s[0],) + e
Here's my (perhaps not totally complete, because your goal is not perfectly clear to me) method:
list_a = [1, 2, 3, 4, 5]
list_b = [3,4,7,8,2]
list_c = [4,6,1,5,8]
Threshold = 12
l = len(list_a)
def total(n):
# convert n to binary form with l digits
mask = bin(n)[2:].zfill(l)
# calculates and returns the corresponding sums from list_b and list_c
return(sum(int(mask[i])*list_b[i] for i in range(l)),sum(int(mask[i])*list_c[i] for i in range(l)))
dic = {n:total(n) for n in range(2**l-1) if max(total(n)) <= Threshold}
print(dic)
# {0: (0, 0), 1: (2, 8), 2: (8, 5), 4: (7, 1), 5: (9, 9), 8: (4, 6), 10: (12, 11), 12: (11, 7), 16: (3, 4), 17: (5, 12), 18: (11, 9), 20: (10, 5), 24: (7, 10)}
This dict's keys are the integers corresponding to the subsets (for example: 24 is 11000 in binary, which corresponds to the {1,2} subset of list_a), and the values are the corresponding sums from list_b and list_c.
Now if all you want are the relevant subsets of list_a, this one will print them (using the same method as in my total(n) function):
print([{list_a[i] for i in range(l) if int(bin(n)[2:].zfill(l)[i])} for n in dic])
# [set(), {5}, {4}, {3}, {3, 5}, {2}, {2, 4}, {2, 3}, {1}, {1, 5}, {1, 4}, {1, 3}, {1, 2}]