Search code examples
pythonsubset

How to append item from list in front of specific list in list of lists?


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

Solution

  • 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}]