Adding a simple cascading solution to generate a Power Set (#975)

* Add a simple cascading version of generating a PowerSet.

* Update README.

* Update README.

* Update README.
This commit is contained in:
Oleksii Trekhleb 2023-01-06 14:37:36 +01:00 committed by GitHub
parent a123b9017d
commit 65e4a7c8b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 12 deletions

View File

@ -99,7 +99,7 @@ a set of rules that precisely define a sequence of operations.
* **Sets** * **Sets**
* `B` [Cartesian Product](src/algorithms/sets/cartesian-product) - product of multiple sets * `B` [Cartesian Product](src/algorithms/sets/cartesian-product) - product of multiple sets
* `B` [FisherYates Shuffle](src/algorithms/sets/fisher-yates) - random permutation of a finite sequence * `B` [FisherYates Shuffle](src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
* `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set (bitwise and backtracking solutions) * `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set (bitwise, backtracking, and cascading solutions)
* `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions) * `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions)
* `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions) * `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions)
* `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS) * `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS)

View File

@ -1,7 +1,7 @@
# Power Set # Power Set
Power set of a set `S` is the set of all of the subsets of `S`, including the Power set of a set `S` is the set of all of the subsets of `S`, including the
empty set and `S` itself. Power set of set `S` is denoted as `P(S)`. empty set and `S` itself. Power set of set `S` is denoted as `P(S)`.
For example for `{x, y, z}`, the subsets For example for `{x, y, z}`, the subsets
are: are:
@ -21,37 +21,37 @@ are:
![Power Set](https://www.mathsisfun.com/sets/images/power-set.svg) ![Power Set](https://www.mathsisfun.com/sets/images/power-set.svg)
Here is how we may illustrate the elements of the power set of the set `{x, y, z}` ordered with respect to Here is how we may illustrate the elements of the power set of the set `{x, y, z}` ordered with respect to
inclusion: inclusion:
![](https://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg) ![](https://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg)
**Number of Subsets** **Number of Subsets**
If `S` is a finite set with `|S| = n` elements, then the number of subsets If `S` is a finite set with `|S| = n` elements, then the number of subsets
of `S` is `|P(S)| = 2^n`. This fact, which is the motivation for the of `S` is `|P(S)| = 2^n`. This fact, which is the motivation for the
notation `2^S`, may be demonstrated simply as follows: notation `2^S`, may be demonstrated simply as follows:
> First, order the elements of `S` in any manner. We write any subset of `S` in > First, order the elements of `S` in any manner. We write any subset of `S` in
the format `{γ1, γ2, ..., γn}` where `γi , 1 ≤ i ≤ n`, can take the value the format `{γ1, γ2, ..., γn}` where `γi , 1 ≤ i ≤ n`, can take the value
of `0` or `1`. If `γi = 1`, the `i`-th element of `S` is in the subset; of `0` or `1`. If `γi = 1`, the `i`-th element of `S` is in the subset;
otherwise, the `i`-th element is not in the subset. Clearly the number of otherwise, the `i`-th element is not in the subset. Clearly the number of
distinct subsets that can be constructed this way is `2^n` as `γi ∈ {0, 1}`. distinct subsets that can be constructed this way is `2^n` as `γi ∈ {0, 1}`.
## Algorithms ## Algorithms
### Bitwise Solution ### Bitwise Solution
Each number in binary representation in a range from `0` to `2^n` does exactly Each number in binary representation in a range from `0` to `2^n` does exactly
what we need: it shows by its bits (`0` or `1`) whether to include related what we need: it shows by its bits (`0` or `1`) whether to include related
element from the set or not. For example, for the set `{1, 2, 3}` the binary element from the set or not. For example, for the set `{1, 2, 3}` the binary
number of `0b010` would mean that we need to include only `2` to the current set. number of `0b010` would mean that we need to include only `2` to the current set.
| | `abc` | Subset | | | `abc` | Subset |
| :---: | :---: | :-----------: | | :---: | :---: | :-----------: |
| `0` | `000` | `{}` | | `0` | `000` | `{}` |
| `1` | `001` | `{c}` | | `1` | `001` | `{c}` |
| `2` | `010` | `{b}` | | `2` | `010` | `{b}` |
| `3` | `011` | `{c, b}` | | `3` | `011` | `{c, b}` |
| `4` | `100` | `{a}` | | `4` | `100` | `{a}` |
| `5` | `101` | `{a, c}` | | `5` | `101` | `{a, c}` |
@ -68,6 +68,44 @@ element.
> See [btPowerSet.js](./btPowerSet.js) file for backtracking solution. > See [btPowerSet.js](./btPowerSet.js) file for backtracking solution.
### Cascading Solution
This is, arguably, the simplest solution to generate a Power Set.
We start with an empty set:
```text
powerSets = [[]]
```
Now, let's say:
```text
originalSet = [1, 2, 3]
```
Let's add the 1st element from the originalSet to all existing sets:
```text
[[]] ← 1 = [[], [1]]
```
Adding the 2nd element to all existing sets:
```text
[[], [1]] ← 2 = [[], [1], [2], [1, 2]]
```
Adding the 3nd element to all existing sets:
```
[[], [1], [2], [1, 2]] ← 3 = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
```
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.
> See [caPowerSet.js](./caPowerSet.js) file for cascading solution.
## References ## References
* [Wikipedia](https://en.wikipedia.org/wiki/Power_set) * [Wikipedia](https://en.wikipedia.org/wiki/Power_set)

View File

@ -0,0 +1,28 @@
import caPowerSet from '../caPowerSet';
describe('caPowerSet', () => {
it('should calculate power set of given set using cascading approach', () => {
expect(caPowerSet([1])).toEqual([
[],
[1],
]);
expect(caPowerSet([1, 2])).toEqual([
[],
[1],
[2],
[1, 2],
]);
expect(caPowerSet([1, 2, 3])).toEqual([
[],
[1],
[2],
[1, 2],
[3],
[1, 3],
[2, 3],
[1, 2, 3],
]);
});
});

View File

@ -0,0 +1,37 @@
/**
* Find power-set of a set using CASCADING approach.
*
* @param {*[]} originalSet
* @return {*[][]}
*/
export default function caPowerSet(originalSet) {
// Let's start with an empty set.
const sets = [[]];
/*
Now, let's say:
originalSet = [1, 2, 3].
Let's add the first element from the originalSet to all existing sets:
[[]] 1 = [[], [1]]
Adding the 2nd element to all existing sets:
[[], [1]] 2 = [[], [1], [2], [1, 2]]
Adding the 3nd element to all existing sets:
[[], [1], [2], [1, 2]] 3 = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
And so on for the rest of the elements from originalSet.
On every iteration the number of sets is doubled, so we'll get 2^n sets.
*/
for (let numIdx = 0; numIdx < originalSet.length; numIdx += 1) {
const existingSetsNum = sets.length;
for (let setIdx = 0; setIdx < existingSetsNum; setIdx += 1) {
const set = [...sets[setIdx], originalSet[numIdx]];
sets.push(set);
}
}
return sets;
}