# python3 program for the above approach.
# Boolean array to check if elements
# represented by a bitmask(subset)
# can be split into two non-empty groups
# having equal sum.
canSplit = [0 for _ in range(1 << 20)]
# Map to store sum of subsets
# and find if there is a subset
# with the current sum.
mp = {}
# Vector of vector to store
# all the bitmasks having the
# same sum together.
subsets = [[] for _ in range(1 << 20)]
# Variable to count subsets
# having unique sums.
ID = 0
# Function to generate all possible
# subsets from first half
# of the array.
def makeSubsets1(i, N, sum, mask, Arr):
global canSplit, mp, subsets, ID
# If first half of the array
# is traversed.
if (i == N):
# If none of the previously formed
# subsets have the same sum
# as the current subset.
if (not sum in mp):
# Increase ID by 1 as the
# subsets having a unique
# sum value has increased by 1.
ID += 1
# Assign the value of sum to ID.
mp[sum] = ID
# Retrieve the subset number
# having this sum.
id = mp[sum]
# Add the bitmask to the vector
# of this particular subset id.
subsets[id].append(mask)
return
# Exclude the current element
# from the subset
makeSubsets1(i + 1, N, sum, mask, Arr)
# Include the current element
# to the first group of the subset.
makeSubsets1(i + 1, N, sum + Arr[i], mask | (1 << i), Arr)
# Include the current element
# to the second group of the subset.
makeSubsets1(i + 1, N, sum - Arr[i], mask | (1 << i), Arr)
# Function to generate all possible
# subsets from second half of array.
def makeSubsets2(i, N, sum, mask, Arr):
global canSplit, mp, subsets, ID
# If the second half
# of the array is traversed.
if (i == N):
# If the current subset sum has
# occurred before in the
# first part of the array, then the
# combined subset from both halves
# of the array forms a valid subset
if (sum in mp):
# Iterate through all the bitmasks
# from the first part of the array
# having the same current sum.
for num in subsets[mp[sum]]:
# Mark the bitwise OR
# of both subsets as TRUE.
canSplit[num | mask] = 1
return
# Exclude the current element
# from the subset.
makeSubsets2(i + 1, N, sum, mask, Arr)
# Include the current element
# to the second group of the subset.
makeSubsets2(i + 1, N, sum + Arr[i], mask | (1 << i),
Arr)
# Include the current element
# to the first group of the subset.
makeSubsets2(i + 1, N, sum - Arr[i], mask | (1 << i),
Arr)
# Utility function to find all subsets from both halves of
# the array.
def UtilCountOfSubsets(N, Arr):
global canSplit, mp, subsets, ID
# Split the array into two parts.
mid = N // 2
# Function calls
makeSubsets1(0, mid, 0, 0, Arr)
makeSubsets2(mid, N, 0, 0, Arr)
ans = 0
# Iterate through all bitmasks
# from 1 to 2^N - 1.
for i in range(1, 1 << N):
# If canSplit[i] is true,
# increase the answer by 1.
ans += canSplit[i]
# Return the answer.
return ans
# Driver code
if __name__ == "__main__":
# Input Array
Arr = [2, 3, 4, 5]
# Size of array
N = len(Arr)
print(UtilCountOfSubsets(N, Arr))
# This code is contributed by rakeshsahni