How to get a subset in a partitioning algorithm?

I have an array, and I would like to split it into two parts so that their sum is equal, for example, [10, 30, 20, 50]can be divided by [10, 40] , [20, 30]. Both have a sum of 50. This is essentially a separation algorithm, but I would like the subsets to not just determine if it is shared. So, I went ahead and did the following:

Update : updated script to handle duplicates

from collections import Counter

def is_partitionable(a):
    possible_sums = [a[0]]
    corresponding_subsets = [[a[0]]]
    target_value = sum(a)/2
    if a[0] == target_value:
        print("yes",[a[0]],a[1:])
        return
    for x in a[1:]:
        temp_possible_sums = []
        for (ind, t) in enumerate(possible_sums):
            cursum = t + x
            if cursum < target_value:
                corresponding_subsets.append(corresponding_subsets[ind] + [x])
                temp_possible_sums.append(cursum)
            if cursum == target_value:
                one_subset = corresponding_subsets[ind] + [x]
                another_subset = list((Counter(a) - Counter(one_subset)).elements())
                print("yes", one_subset,another_subset)
                return
        possible_sums.extend(temp_possible_sums)
    print("no")
    return

is_partitionable(list(map(int, input().split())))

Example input and output:

>>> is_partitionable([10,30,20,40])
yes [10, 40] [30, 20]
>>> is_partitionable([10,30,20,20])
yes [10, 30] [20, 20]
>>> is_partitionable([10,30,20,10])
no

I essentially save the corresponding values ​​that were added to get the value in corresponding_subsets. But, as the size increases a, it is obvious that there corresponding_subsetswill be too many subscriptions (equal to the number of elements in possible_sums). Is there a better / more efficient way to do this?

+4
2

, . , n, arr ( , 1). A B, arr A B , . arr A, B. , (, i- ) A, -a[i], B, a[i]. , , 0, . n ( ). arr = {10,20,30,40}. .

set_1 = {10,-10} # -10 if it goes to Team A and 10 if goes to B

set_2 = {30,-10,10,-30} # four options as we add -20 and 20

set_3 = {60,0,20,-40,-20,-60} # note we don't need to store duplicates

set_4 = {100,20,40,-40,60,-20,-80,0,-60,-100} # see there is a zero means our task is possible

, - 0 , , i- a[i] a[i] -a[i], .. Team A B.

. , n set_1 set_n. list_A, , A list_B. set_n, , , current_set, n. 0 , , current_element, 0. ( , 1 n , , ). , 0 , .. .

sets = [ [0], #see this dummy set it is important, this is set_0
              #because initially we add -arr[0] or arr[0] to 0
         [10,-10],
         [30,-10,10,-30],
         [60,0,20,-40,-20,-60],
         [100,20,40,-40,60,-20,-80,0,-60,-100]]

# my array is 1 based so ignore the zero
arr = [0,10,20,30,40]

list_A = []
list_B = []

current_element = 0
current_set = 4 # Total number of sets in this case is n=4

while current_set >= 1:
   print current_set,current_element
   for element in sets[current_set-1]:
     if element + arr[current_set] == current_element:
       list_B.append(arr[current_set])
       current_element = element
       current_set -= 1
       break
     elif element - arr[current_set] == current_element:
       list_A.append(arr[current_set])
       current_element = element
       current_set -= 1
       break


print list_A,list_B
+3

@sasha algo .

def my_part(my_list):
    item = my_list.pop()
    balance = []
    temp = [item, -item]
    while len(my_list) != 0:
        new_player = my_list.pop()
        for i, items in enumerate(temp):
            balance.append(items + new_player)
            balance.append(items - new_player)
        temp = balance[:]
    balance = set(balance)
    if 0 in balance:
        return 'YES'
    else:
        return 'NO'

.

0

Source: https://habr.com/ru/post/1654718/


All Articles