Skip to content

Commit b0c55ec

Browse files
mmapplebecktrekhleb
authored andcommitted
add recursive solution to permutations with repetitions problem (trekhleb#52)
* add recursive solution to permutations with repetitions problem * fix untested function, failing test * add comments
1 parent 8d3f83c commit b0c55ec

File tree

4 files changed

+87
-49
lines changed

4 files changed

+87
-49
lines changed
Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,8 @@
11
import permutateWithRepetitions from '../permutateWithRepetitions';
2+
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
23

34
describe('permutateWithRepetitions', () => {
45
it('should permutate string with repetition', () => {
5-
const permutations0 = permutateWithRepetitions([]);
6-
expect(permutations0).toEqual([]);
7-
8-
const permutations1 = permutateWithRepetitions(['A']);
9-
expect(permutations1).toEqual([
10-
['A'],
11-
]);
12-
13-
const permutations2 = permutateWithRepetitions(['A', 'B']);
14-
expect(permutations2).toEqual([
15-
['A', 'A'],
16-
['A', 'B'],
17-
['B', 'A'],
18-
['B', 'B'],
19-
]);
20-
21-
const permutations3 = permutateWithRepetitions(['A', 'B', 'C']);
22-
expect(permutations3).toEqual([
23-
['A', 'A', 'A'],
24-
['A', 'A', 'B'],
25-
['A', 'A', 'C'],
26-
['A', 'B', 'A'],
27-
['A', 'B', 'B'],
28-
['A', 'B', 'C'],
29-
['A', 'C', 'A'],
30-
['A', 'C', 'B'],
31-
['A', 'C', 'C'],
32-
['B', 'A', 'A'],
33-
['B', 'A', 'B'],
34-
['B', 'A', 'C'],
35-
['B', 'B', 'A'],
36-
['B', 'B', 'B'],
37-
['B', 'B', 'C'],
38-
['B', 'C', 'A'],
39-
['B', 'C', 'B'],
40-
['B', 'C', 'C'],
41-
['C', 'A', 'A'],
42-
['C', 'A', 'B'],
43-
['C', 'A', 'C'],
44-
['C', 'B', 'A'],
45-
['C', 'B', 'B'],
46-
['C', 'B', 'C'],
47-
['C', 'C', 'A'],
48-
['C', 'C', 'B'],
49-
['C', 'C', 'C'],
50-
]);
51-
52-
const permutations4 = permutateWithRepetitions(['A', 'B', 'C', 'D']);
53-
expect(permutations4.length).toBe(4 * 4 * 4 * 4);
6+
testPermutateWithRepetitionsFn(permutateWithRepetitions);
547
});
558
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive';
2+
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
3+
4+
describe('permutateWithRepetitionsRecursive', () => {
5+
it('should permutate string with repetition', () => {
6+
testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive);
7+
});
8+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
export default function testPermutateWithRepetitionsFn(fn) {
2+
const permutations0 = fn([]);
3+
expect(permutations0).toEqual([]);
4+
5+
const permutations1 = fn(['A']);
6+
expect(permutations1).toEqual([
7+
['A'],
8+
]);
9+
10+
const permutations2 = fn(['A', 'B']);
11+
expect(permutations2).toEqual([
12+
['A', 'A'],
13+
['A', 'B'],
14+
['B', 'A'],
15+
['B', 'B'],
16+
]);
17+
18+
const permutations3 = fn(['A', 'B', 'C']);
19+
expect(permutations3).toEqual([
20+
['A', 'A', 'A'],
21+
['A', 'A', 'B'],
22+
['A', 'A', 'C'],
23+
['A', 'B', 'A'],
24+
['A', 'B', 'B'],
25+
['A', 'B', 'C'],
26+
['A', 'C', 'A'],
27+
['A', 'C', 'B'],
28+
['A', 'C', 'C'],
29+
['B', 'A', 'A'],
30+
['B', 'A', 'B'],
31+
['B', 'A', 'C'],
32+
['B', 'B', 'A'],
33+
['B', 'B', 'B'],
34+
['B', 'B', 'C'],
35+
['B', 'C', 'A'],
36+
['B', 'C', 'B'],
37+
['B', 'C', 'C'],
38+
['C', 'A', 'A'],
39+
['C', 'A', 'B'],
40+
['C', 'A', 'C'],
41+
['C', 'B', 'A'],
42+
['C', 'B', 'B'],
43+
['C', 'B', 'C'],
44+
['C', 'C', 'A'],
45+
['C', 'C', 'B'],
46+
['C', 'C', 'C'],
47+
]);
48+
49+
const permutations4 = fn(['A', 'B', 'C', 'D']);
50+
expect(permutations4.length).toBe(4 * 4 * 4 * 4);
51+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @param {*[]} permutationOptions
3+
* @return {*[]}
4+
*/
5+
export default function permutateWithRepetitionsRecursive(
6+
options,
7+
n = options.length || 0,
8+
prefix = [],
9+
perms = [],
10+
) {
11+
// If initial options are null or empty then return empty array
12+
if (!options || !options.length) return [];
13+
14+
// If no more iterations then add current prefix to perms array
15+
if (n === 0) {
16+
perms.push(prefix);
17+
return perms;
18+
}
19+
20+
// Recursively find permutations and store in perms array
21+
options.forEach((option) => {
22+
permutateWithRepetitionsRecursive(options, n - 1, prefix.concat([option]), perms);
23+
});
24+
25+
return perms;
26+
}

0 commit comments

Comments
 (0)