Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5eb1195

Browse files
committed
Add backtracking solution for finding the power-set of a set.
1 parent bffacf0 commit 5eb1195

File tree

7 files changed

+139
-29
lines changed

7 files changed

+139
-29
lines changed

‎README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ a set of rules that precisely define a sequence of operations.
7777
* **Sets**
7878
* `B` [Cartesian Product](src/algorithms/sets/cartesian-product) - product of multiple sets
7979
* `B` [Fisher–Yates Shuffle](src/algorithms/sets/fisher-yates) - random permutation of a finite sequence
80-
* `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set
80+
* `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set (bitwise and backtracking solutions)
8181
* `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions)
8282
* `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions)
8383
* `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS)
@@ -190,6 +190,7 @@ if it satisfies all conditions, and only then continue generating subsequent sol
190190
different path of finding a solution. Normally the DFS traversal of state-space is being used.
191191
* `B` [Jump Game](src/algorithms/uncategorized/jump-game)
192192
* `B` [Unique Paths](src/algorithms/uncategorized/unique-paths)
193+
* `B` [Power Set](src/algorithms/sets/power-set) - all subsets of a set
193194
* `A` [Hamiltonian Cycle](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once
194195
* `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens)
195196
* `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour)

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,62 @@
11
# Power Set
22

3-
Power set of a set A is the set of all of the subsets of A.
3+
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)`.
45

5-
Eg. for `{x, y, z}`, the subsets are : `{{}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z}}`
6+
For example for `{x, y, z}`, the subsets
7+
are:
8+
9+
```text
10+
{
11+
{}, // (also denoted empty set ∅ or the null set)
12+
{x},
13+
{y},
14+
{z},
15+
{x, y},
16+
{x, z},
17+
{y, z},
18+
{x, y, z}
19+
}
20+
```
621

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

24+
Here is how we may illustrate the elements of the power set of the set `{x, y, z}` ordered with respect to
25+
inclusion:
26+
27+
![](https://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg)
28+
29+
**Number of Subsets**
30+
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
33+
notation `2^S`, may be demonstrated simply as follows:
34+
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
37+
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
39+
distinct subsets that can be constructed this way is `2^n` as `γi ∈ {0, 1}`.
40+
41+
## Algorithms
42+
43+
### Bitwise Solution
44+
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
48+
number of `0b010` would mean that we need to include only `2` to the current set.
49+
50+
> See [bwPowerSet.js](./bwPowerSet.js) file for bitwise solution.
51+
52+
### Backtracking Solution
53+
54+
In backtracking approach we're constantly trying to add next element of the set
55+
to the subset, memorizing it and then removing it and try the same with the next
56+
element.
57+
58+
> See [btPowerSet.js](./btPowerSet.js) file for backtracking solution.
59+
960
## References
1061

1162
* [Wikipedia](https://en.wikipedia.org/wiki/Power_set)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import btPowerSet from '../btPowerSet';
2+
3+
describe('btPowerSet', () => {
4+
it('should calculate power set of given set using backtracking approach', () => {
5+
expect(btPowerSet([1])).toEqual([
6+
[],
7+
[1],
8+
]);
9+
10+
expect(btPowerSet([1, 2, 3])).toEqual([
11+
[],
12+
[1],
13+
[1, 2],
14+
[1, 2, 3],
15+
[1, 3],
16+
[2],
17+
[2, 3],
18+
[3],
19+
]);
20+
});
21+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import bwPowerSet from '../bwPowerSet';
2+
3+
describe('bwPowerSet', () => {
4+
it('should calculate power set of given set using bitwise approach', () => {
5+
expect(bwPowerSet([1])).toEqual([
6+
[],
7+
[1],
8+
]);
9+
10+
expect(bwPowerSet([1, 2, 3])).toEqual([
11+
[],
12+
[1],
13+
[2],
14+
[1, 2],
15+
[3],
16+
[1, 3],
17+
[2, 3],
18+
[1, 2, 3],
19+
]);
20+
});
21+
});

‎src/algorithms/sets/power-set/__test__/powerSet.test.js

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @param {*[]} originalSet - Original set of elements we're forming power-set of.
3+
* @param {*[][]} allSubsets - All subsets that have been formed so far.
4+
* @param {*[]} currentSubSet - Current subset that we're forming at the moment.
5+
* @param {number} startAt - The position of in original set we're starting to form current subset.
6+
* @return {*[][]} - All subsets of original set.
7+
*/
8+
function btPowerSetRecursive(originalSet, allSubsets = [[]], currentSubSet = [], startAt = 0) {
9+
// In order to avoid duplication we need to start from next element every time we're forming a
10+
// subset. If we will start from zero then we'll have duplicates like {3, 3, 3}.
11+
for (let position = startAt; position < originalSet.length; position += 1) {
12+
// Let's push current element to the subset.
13+
currentSubSet.push(originalSet[position]);
14+
// Current subset is already valid so let's memorize it.
15+
allSubsets.push([...currentSubSet]);
16+
// Let's try to form all other subsets for the current subset.
17+
btPowerSetRecursive(originalSet, allSubsets, currentSubSet, position + 1);
18+
// BACKTRACK. Exclude last element from the subset and try the next one.
19+
currentSubSet.pop();
20+
}
21+
22+
// Return all subsets of a set.
23+
return allSubsets;
24+
}
25+
26+
/**
27+
* Find power-set of a set using BACKTRACKING approach.
28+
*
29+
* @param {*[]} originalSet
30+
* @return {*[][]}
31+
*/
32+
export default function btPowerSet(originalSet) {
33+
return btPowerSetRecursive(originalSet);
34+
}

‎src/algorithms/sets/power-set/powerSet.js renamed to ‎src/algorithms/sets/power-set/bwPowerSet.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Find power-set of a set using BITWISE approach.
3+
*
4+
* @param {*[]} originalSet
5+
* @return {*[][]}
6+
*/
17
export default function powerSet(originalSet) {
28
const subSets = [];
39

@@ -7,8 +13,8 @@ export default function powerSet(originalSet) {
713
const numberOfCombinations = 2 ** originalSet.length;
814

915
// Each number in binary representation in a range from 0 to 2^n does exactly what we need:
10-
// it shoes by its bits (0 or 1) whether to include related element from the set or not.
11-
// For example, for the set {1, 2, 3} the binary number of 010 would mean that we need to
16+
// it shows by its bits (0 or 1) whether to include related element from the set or not.
17+
// For example, for the set {1, 2, 3} the binary number of 0b010 would mean that we need to
1218
// include only "2" to the current set.
1319
for (let combinationIndex = 0; combinationIndex < numberOfCombinations; combinationIndex += 1) {
1420
const subSet = [];

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /