简体   繁体   中英

list of elements from a list that sum is equal or less than to a given number

n = [5, 5, 4, 6] # number of list
X = 8 # user have to pass 2 input has X, Y.
Y = 8
result1 = [5] or [5] or [4] or [6] # if I choose 5. n = [5,4,6]
# total = sum(result1).
# total <= user X.
result2 = [5] or [4] or [6]
# total = sum(result2).
# total <= user Y. 
Ans : 2

n = [6,5,2,1,8] 
X = 17
Y = 5
X = [8, 6, 2, 1] 
Y = [5] 
Ans: 5

n = [6,5,5,4,3] 
X = 8 
Y = 9
X = [5,3] # if I choose 5,3 remaining list of elements will be [6,5,4]
Y = [5,4]
Ans : 4

1.I was unable to find this logic trick. so kindly help me out. 2.I tried to solve like Subset Sum. But still I couldn't figure out logic. Note: using python language.

Unless you are looking for a solution that maximizes the two values, you can get the closest sum for each number (removing the items of the first result from the list before the second search).

If that is the case, you can approach it recursively by picking each number as the first in the combination and recursing with the remaining numbers to get close to the remaining sum.

To process Y, you'll need a second function that removes (subtracts) the X result from your list.

def sumless(A,S):
    if not S: return []       # target reached
    closest = []              # track closest combo
    for i,a in enumerate(A):  # try each number as start of combo
        if a>S: continue      # skip nnumbers that are too large
        sl = [a] + sumless(A[i+1:],S-a) # find closest with rest
        if sum(sl)>=sum(closest):  
            closest = sl      # track closest combo
    return closest


def subtract(A,B):
    B = B.copy()
    return [a for a in A if a not in B or B.pop(B.index(a))*0 ]

Output:

n = [5,5,4,6] 
X = 8
Y = 8
Xn = sumless(n,X)
Yn = sumless(subtract(n,Xn),Y)
print("X",Xn) # [6]
print("Y",Yn) # [5]

n = [6,5,2,1,8] 
X = 17
Y = 5
Xn = sumless(n,X)
Yn = sumless(subtract(n,Xn),Y)
print(Xn) # [6,2,1,8]
print(Yn) # [5]

n = [6,5,5,4,3] 
X = 8 
Y = 9
Xn = sumless(n,X)
Yn = sumless(subtract(n,Xn),Y)
print(Xn) # [5,3]
print(Yn) # [5,4]

If you do need to get the largest possible 'closest' sums, you will need to combine all subsets of the two targets and find the best pair of subsets (ie where the total sum is greatest):

def sumGen(A,S):                        # sum set generator
    if not S: return                    # target reached
    for i,a in enumerate(A):            # try each number as start 
        if a>S: continue                # skip if too large
        yield [a]                       # return single value
        for sl in sumGen(A[i+1:],S-a):  # combine rest
            yield [a]+sl                # return longer combos

def twoSums(A,X,Y):
    bestX,bestY,bestSum = [],[],0       # track closest pair of combos
    for Xn in sumGen(A,X):              # subsets <= X
        for Yn in sumGen(subtract(A,Xn),Y): # subsets <= Y (from rest)
            if sum(Xn)+sum(Yn)>bestSum:     # track closest
                bestX,bestY,bestSum = Xn,Yn,sum(Xn)+sum(Yn)
    return bestX,bestY

Output: (same as above given that your examples don't highlight the distinction between a naive search and an optimized one)

n = [5,5,4,6] 
X = 8
Y = 8
print(*twoSums(n,X,Y)) # [6],[5]


n = [6,5,2,1,8] 
X = 17
Y = 5
print(*twoSums(n,X,Y)) # [6, 2, 1, 8] [5]

n = [6,5,5,4,3] 
X = 8 
Y = 9
print(*twoSums(n,X,Y)) # [5, 3] [5, 4]

This would make a difference though:

n = [6,5,5,4,3,2] 
X = 9 
Y = 15
Xn = sumless(n,X)
Yn = sumless(subtract(n,Xn),Y)
print(Xn) # [4,3,2] = 9
print(Yn) # [6,5]   = 11
print(*twoSums(n,X,Y)) # [6, 3] [5, 5, 4] = 9, 14

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