Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate the power-set of a given List?

I'm trying to generate a collection of all 2^N - 1 possible combinations of a given List of length N. The collection will map the number of elements in a combination to an ordered list of combinations containing combinations of the specific length. For instance, for the List:

[A, B, C, D] 

I want to generate the map:

{     1 -> [{A}, {B}, {C}, {D}]     2 -> [{A, B}, {A, C}, {A, D}, {B, C}, {B, D}, {C, D}]     3 -> [{A, B, C}, {A, B, D}, {A, C, D}, {B, C, D}]     4 -> [{A, B, C, D}] } 

The generated database should maintain the original order (where [] represents an ordered series (List), and {} represents an un-ordered group (Set)), and run as fast as possible.

I was struggling with some recursive code all day (I know the implementation should be recursive) but couldn't get to the bottom of it.

Is there a reference I can use/a ready implementation of such algorithm?

like image 986
Elist Avatar asked Jan 05 '14 15:01

Elist


People also ask

How do you create a power set in Python?

Another way one can generate the powerset is by generating all binary numbers that have n bits. As a power set the amount of number with n digits is 2 ^ n . The principle of this algorithm is that an element could be present or not in a subset as a binary digit could be one or zero but not both.

What is a power set of a given set?

A power set is defined as the set or group of all subsets for any given set, including the empty set, which is denoted by {}, or, ϕ. A set that has 'n' elements has 2n subsets in all. For example, let Set A = {1,2,3}, therefore, the total number of elements in the set is 3.


2 Answers

What you're looking for is essentially the power set (minus perhaps the empty set). Guava actually has a method for this: Sets.powerSet(). You can view the source of the Sets class to see how the method is implemented if you want to write it yourself; you might need to modify it to return a List instead of a Set since you want to preserve order, although this change should not be too drastic. Once you have the power set, it should be trivial to iterate over it and construct the map you want.

like image 58
arshajii Avatar answered Sep 21 '22 06:09

arshajii


What you're asking is generating all possible subsets of a set. You can think of it as iterating over all possible binary arrays of size N (the size of your list):

000000...000 000000...001 000000...010 000000...011 etc. 

Why is that? The answer is simple: 1 indicates that an element exists in a subset, while 0 indicates that it is absent.

So, the basic algorithm is obvious:

s = [A, B, C, D]  for i=0 to 2^N-1:    b = convert_number_to_bin_array(i)    ss = calculate_subset_based_on_bin_array(s, b)    print ss 

Where calculate_subset_based_on_bin_array iterates on b and s and selects elements from s[current] where b[current] = 1.

The above will print out all existing subsets. You can adapt this algorithm in order to get the map that you've asked for in your question.

like image 20
Michael Spector Avatar answered Sep 23 '22 06:09

Michael Spector