monir zaman
monir zaman

Reputation: 351

How can I get all the disjoint subsets of a list of elements, and if join together it is same as the initial list in python?

Suppose, a set [0,1,2] How can I get all the list of sets that if join together, it results= [0,1,2] Those subsets could be,

[[0],[1],[2]]

[[0,1],[2]]

[[0],[1,2]]

[[1],[0,2]]

[[0,1,2]]

This is the python code that I tried,

import collections

def get_subsets(fullset):
    listrep = list(fullset)
    n = len(listrep)
    return [[listrep[k] for k in range(n) if i&1<<k] for i in range(2**n)]


P_Set=list(df_distance.columns)
P_Set.pop(P_Set[-1])
powerSet=get_subsets(P_Set)
powerSet=get_subsets([0,1,2,3,4])


# Finding the disjoint subset that union make fullset
def common_data(list1, list2): 
    result = False
    # traverse in the 1st list 
    for x in list1: 
        # traverse in the 2nd list 
        for y in list2: 
            # if one common 
            if x == y: 
                result = True
                return result                   
    return result

# Delete the empty list from the power list
powerSet = [x for x in powerSet if x]

# Finding the subsets
disjointSubsetList=[]
# initialSet=P_Set
initialSet=[0,1,2,3,4]
coalitionSet=[]

for i in powerSet:
    coalitionSet=[]
    coalitionSet.append(i)
    for j in powerSet:
        if collections.Counter(i) != collections.Counter(j):
            if not common_data(i,j):
                coalitionSet.append(j)
            if collections.Counter(list(itertools.chain.from_iterable(coalitionSet))) == collections.Counter(initialSet):
                disjointSubsetList.append(coalitionSet)
                coalitionSet=[]

The result is fine for the list [0,1,2] but if its [0,1,2,3,4] then the result is not correct.

Thanks in advance for your time.

Upvotes: 0

Views: 439

Answers (1)

0xF4D3C0D3
0xF4D3C0D3

Reputation: 837

# https://github.com/0xF4D3C0D3/snippets/blob/master/algorithm/partition.py

import itertools


def partition(list_, k):
    """
    partition([1, 2, 3, 4], 2) -> [[1], [2, 3, 4]], [[1, 2], [3, 4]], ..., [[1, 3], [2, 4]], [[3], [1, 2, 4]]
    """
    if k == 1:  # base case 1: k == 1, just yield itself as a list
        yield [list_]
    elif k == len(list_):  # base case 2: k == len(list_), yield each item in the list wrapped in a list
        yield [[s] for s in list_]
    else:
        head, *tail = list_  # head = the first element, tail = the rest
        for p in partition(tail, k-1):  # case 1: head -> 1, partition(tail, k-1) -> k-1.
                                        # head + partition(tail, k-1) -> 1+k-1 -> k
            yield [[head], *p]
        for p in partition(tail, k):  # case 2: head -> 1, partition(tail, k) -> k.
                                      # bloat x to [e1, e2, e3] -> [[x+e1, e2, e3], [e1, x+e2, e3], [e1, e2, x+e3]]
            for i in range(len(p)):
                yield p[:i] + [[head] + p[i]] + p[i+1:]  # bloat head to partition(tail, k) -> k

def get_all_disjoint_sets(iterable):
    l = list(iterable)
    return itertools.chain.from_iterable(list(partition(l, i)) for i in range(1, len(l)+1))

print('\n'.join(map(str, get_all_disjoint_sets([0, 1, 2]))))
'''
[[0, 1, 2]]
[[0], [1, 2]]
[[0, 1], [2]]
[[1], [0, 2]]
[[0], [1], [2]]
'''

list(get_all_disjoint_sets([0, 1, 2]))
# [[[0, 1, 2]], [[0], [1, 2]], [[0, 1], [2]], [[1], [0, 2]], [[0], [1], [2]]]

Upvotes: 1

Related Questions