-1

I have to check if it is possible to get sum from given numbers >to be strictly greater than given sum

for example:

if given sum is 9 and the given numbers are [3,5,7] then the correct answer is 1*3 +1*7=10>9 so the out put should be [1,0,1]

example2:

if given sum is 13 and the numbers are [1,3,5] then correct answer is 0*1+3*3+1*5=14>13 but 9*1+0*3+5=14 is >wrong so the correct output is [0,3,1] how to approach for this problem

gaurav
  • 15
  • 2
  • What is the constraint that makes `0*1+3*3+1*5=14` correct but `9*1+0*3+5=14` wrong, given `[1, 3, 5]`? – DarrylG Feb 09 '20 at 12:18
  • here 0,3,1 are multiplier or in other words repeatition are allowed.for example if given sum is 9 and the given numbers that should be used is [3,5,9] then we have to use as minimum numbers from the given array to form a sum just greater than given sum i.e – gaurav Feb 09 '20 at 13:10
  • So you mean given array a of non-negative integers, find array b, where 1) b has non-negative integers, 2) dot product between a and b is greater than the given sum, and 3) sum of elements of b are a minimum? – DarrylG Feb 09 '20 at 13:15
  • In the case of `[1, 3, 5]`, is there a preference between solutions `[0, 3, 1]` and `[1, 1, 2]`? Both solutions have a dot product of 14 and the sum of their elements is 4. – DarrylG Feb 09 '20 at 13:42
  • No there is no preferences both are correct – gaurav Feb 10 '20 at 14:08
  • @gaurav--thanks posted an answer with that in mind. – DarrylG Feb 10 '20 at 17:07

1 Answers1

0

A solution can be obtained using a version of the unbounded Knapsack algorithm.

Here we modify code from Python Unbound Knapsack

Modify with two objectives:

  1. Minimized the count of the values used from the array

  2. Create the max sum less than the limit (i.e. given sum + 1)

def knapsack_unbounded_dp(arr, C):
    C += 1  # actual limit

    # Form index value pairs (to keep track of the original indexes after sorting)
    items = [(i, v) for i, v in enumerate(arr)]

    # Sort values in descending order
    items = sorted(items, key=lambda item: item[1], reverse=True)

    # Sack keeps track of:
    #  max value so i.e. sack[0] and
    # count of how many each item are in the sack i.e. sack[1]
    sack = [(0, [0 for i in items]) for i in range(0, C+1)]   # value, [item counts]

    for i,item in enumerate(items):
        # For current item we check if a previous entry could have done better
        # by adding this item to the sack
        index, value = item
        for c in range(value, C+1):   # check all previous values
            sackwithout = sack[c-value]  # previous max sack to try adding this item to
            trial = sackwithout[0] + value  # adding value to max without using it
            used = sackwithout[1][i]        # count of i-them item
            if sack[c][0] < trial:
                # old max sack with this added item is better
                sack[c] = (trial, sackwithout[1][:])
                sack[c][1][i] +=1   # use one more

    value, bagged = sack[C]

    # index and count of each array value
    new_bagged = [(i, v) for (i, _), v in zip(items, bagged)]

    # Re-sort based upon original order of array indexes
    new_bagged.sort(key=lambda t: t[0])

    # counts based upon original array order
    cnts = [v for i, v in new_bagged]

return sum(cnts), value, cnts

Test Code

for t in [([1, 3, 5], 8), ([3, 5, 7], 9), ([1, 3, 5], 13)]:
  result = knapsack_unbounded_dp(t[0], t[1])
  print(f'Test: {t[0]}, Given Sum {t[1]}')
  print(f'Result counts {result[2]}, with max sum {result[1]}, Total Count {result[0]}\n')

Output

Test: [1, 3, 5], Given Sum 8
Result counts [0, 3, 0], with max sum 9, Total Count 3

Test: [3, 5, 7], Given Sum 9
Result counts [0, 2, 0], with max sum 10, Total Count 2

Test: [1, 3, 5], Given Sum 13
Result counts [0, 3, 1], with max sum 14, Total Count 4
DarrylG
  • 16,732
  • 2
  • 17
  • 23