Skip to content

Commit 65e4a7c

Browse files
authoredJan 6, 2023
Adding a simple cascading solution to generate a Power Set (trekhleb#975)
* Add a simple cascading version of generating a PowerSet. * Update README. * Update README. * Update README.
1 parent a123b90 commit 65e4a7c

File tree

4 files changed

+115
-12
lines changed

4 files changed

+115
-12
lines changed
 

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ a set of rules that precisely define a sequence of operations.
9999
* **Sets**
100100
* `B` [Cartesian Product](src/algorithms/sets/cartesian-product) - product of multiple sets
101101
* `B` [Fisher–Yates Shuffle](src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
102-
* `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set (bitwise and backtracking solutions)
102+
* `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set (bitwise, backtracking, and cascading solutions)
103103
* `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions)
104104
* `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions)
105105
* `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS)

‎src/algorithms/sets/power-set/README.md

+49-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Power Set
22

33
Power set of a set `S` is the set of all of the subsets of `S`, including the
4-
empty set and `S` itself. Power set of set `S` is denoted as `P(S)`.
4+
empty set and `S` itself. Power set of set `S` is denoted as `P(S)`.
55

66
For example for `{x, y, z}`, the subsets
77
are:
@@ -21,37 +21,37 @@ are:
2121

2222
![Power Set](https://www.mathsisfun.com/sets/images/power-set.svg)
2323

24-
Here is how we may illustrate the elements of the power set of the set `{x, y, z}` ordered with respect to
24+
Here is how we may illustrate the elements of the power set of the set `{x, y, z}` ordered with respect to
2525
inclusion:
2626

2727
![](https://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg)
2828

2929
**Number of Subsets**
3030

31-
If `S` is a finite set with `|S| = n` elements, then the number of subsets
32-
of `S` is `|P(S)| = 2^n`. This fact, which is the motivation for the
31+
If `S` is a finite set with `|S| = n` elements, then the number of subsets
32+
of `S` is `|P(S)| = 2^n`. This fact, which is the motivation for the
3333
notation `2^S`, may be demonstrated simply as follows:
3434

35-
> First, order the elements of `S` in any manner. We write any subset of `S` in
36-
the format `{γ1, γ2, ..., γn}` where `γi , 1 ≤ i ≤ n`, can take the value
35+
> First, order the elements of `S` in any manner. We write any subset of `S` in
36+
the format `{γ1, γ2, ..., γn}` where `γi , 1 ≤ i ≤ n`, can take the value
3737
of `0` or `1`. If `γi = 1`, the `i`-th element of `S` is in the subset;
38-
otherwise, the `i`-th element is not in the subset. Clearly the number of
38+
otherwise, the `i`-th element is not in the subset. Clearly the number of
3939
distinct subsets that can be constructed this way is `2^n` as `γi ∈ {0, 1}`.
4040

4141
## Algorithms
4242

4343
### Bitwise Solution
4444

45-
Each number in binary representation in a range from `0` to `2^n` does exactly
46-
what we need: it shows by its bits (`0` or `1`) whether to include related
47-
element from the set or not. For example, for the set `{1, 2, 3}` the binary
45+
Each number in binary representation in a range from `0` to `2^n` does exactly
46+
what we need: it shows by its bits (`0` or `1`) whether to include related
47+
element from the set or not. For example, for the set `{1, 2, 3}` the binary
4848
number of `0b010` would mean that we need to include only `2` to the current set.
4949

5050
| | `abc` | Subset |
5151
| :---: | :---: | :-----------: |
5252
| `0` | `000` | `{}` |
5353
| `1` | `001` | `{c}` |
54-
| `2` | `010` | `{b}` |
54+
| `2` | `010` | `{b}` |
5555
| `3` | `011` | `{c, b}` |
5656
| `4` | `100` | `{a}` |
5757
| `5` | `101` | `{a, c}` |
@@ -68,6 +68,44 @@ element.
6868

6969
> See [btPowerSet.js](./btPowerSet.js) file for backtracking solution.
7070
71+
### Cascading Solution
72+
73+
This is, arguably, the simplest solution to generate a Power Set.
74+
75+
We start with an empty set:
76+
77+
```text
78+
powerSets = [[]]
79+
```
80+
81+
Now, let's say:
82+
83+
```text
84+
originalSet = [1, 2, 3]
85+
```
86+
87+
Let's add the 1st element from the originalSet to all existing sets:
88+
89+
```text
90+
[[]] ← 1 = [[], [1]]
91+
```
92+
93+
Adding the 2nd element to all existing sets:
94+
95+
```text
96+
[[], [1]] ← 2 = [[], [1], [2], [1, 2]]
97+
```
98+
99+
Adding the 3nd element to all existing sets:
100+
101+
```
102+
[[], [1], [2], [1, 2]] ← 3 = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
103+
```
104+
105+
And so on, for the rest of the elements from the `originalSet`. On every iteration the number of sets is doubled, so we'll get `2^n` sets.
106+
107+
> See [caPowerSet.js](./caPowerSet.js) file for cascading solution.
108+
71109
## References
72110

73111
* [Wikipedia](https://en.wikipedia.org/wiki/Power_set)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import caPowerSet from '../caPowerSet';
2+
3+
describe('caPowerSet', () => {
4+
it('should calculate power set of given set using cascading approach', () => {
5+
expect(caPowerSet([1])).toEqual([
6+
[],
7+
[1],
8+
]);
9+
10+
expect(caPowerSet([1, 2])).toEqual([
11+
[],
12+
[1],
13+
[2],
14+
[1, 2],
15+
]);
16+
17+
expect(caPowerSet([1, 2, 3])).toEqual([
18+
[],
19+
[1],
20+
[2],
21+
[1, 2],
22+
[3],
23+
[1, 3],
24+
[2, 3],
25+
[1, 2, 3],
26+
]);
27+
});
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Find power-set of a set using CASCADING approach.
3+
*
4+
* @param {*[]} originalSet
5+
* @return {*[][]}
6+
*/
7+
export default function caPowerSet(originalSet) {
8+
// Let's start with an empty set.
9+
const sets = [[]];
10+
11+
/*
12+
Now, let's say:
13+
originalSet = [1, 2, 3].
14+
15+
Let's add the first element from the originalSet to all existing sets:
16+
[[]] ← 1 = [[], [1]]
17+
18+
Adding the 2nd element to all existing sets:
19+
[[], [1]] ← 2 = [[], [1], [2], [1, 2]]
20+
21+
Adding the 3nd element to all existing sets:
22+
[[], [1], [2], [1, 2]] ← 3 = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
23+
24+
And so on for the rest of the elements from originalSet.
25+
On every iteration the number of sets is doubled, so we'll get 2^n sets.
26+
*/
27+
for (let numIdx = 0; numIdx < originalSet.length; numIdx += 1) {
28+
const existingSetsNum = sets.length;
29+
30+
for (let setIdx = 0; setIdx < existingSetsNum; setIdx += 1) {
31+
const set = [...sets[setIdx], originalSet[numIdx]];
32+
sets.push(set);
33+
}
34+
}
35+
36+
return sets;
37+
}

0 commit comments

Comments
 (0)
Please sign in to comment.