add recursive solution to permutations with repetitions problem (#52)

* add recursive solution to permutations with repetitions problem

* fix untested function, failing test

* add comments
This commit is contained in:
Matt Mapplebeck 2018-06-13 01:03:56 -04:00 committed by Oleksii Trekhleb
parent 8d3f83cfb7
commit b0c55ec817
4 changed files with 87 additions and 49 deletions

View File

@ -1,55 +1,8 @@
import permutateWithRepetitions from '../permutateWithRepetitions';
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
describe('permutateWithRepetitions', () => {
it('should permutate string with repetition', () => {
const permutations0 = permutateWithRepetitions([]);
expect(permutations0).toEqual([]);
const permutations1 = permutateWithRepetitions(['A']);
expect(permutations1).toEqual([
['A'],
]);
const permutations2 = permutateWithRepetitions(['A', 'B']);
expect(permutations2).toEqual([
['A', 'A'],
['A', 'B'],
['B', 'A'],
['B', 'B'],
]);
const permutations3 = permutateWithRepetitions(['A', 'B', 'C']);
expect(permutations3).toEqual([
['A', 'A', 'A'],
['A', 'A', 'B'],
['A', 'A', 'C'],
['A', 'B', 'A'],
['A', 'B', 'B'],
['A', 'B', 'C'],
['A', 'C', 'A'],
['A', 'C', 'B'],
['A', 'C', 'C'],
['B', 'A', 'A'],
['B', 'A', 'B'],
['B', 'A', 'C'],
['B', 'B', 'A'],
['B', 'B', 'B'],
['B', 'B', 'C'],
['B', 'C', 'A'],
['B', 'C', 'B'],
['B', 'C', 'C'],
['C', 'A', 'A'],
['C', 'A', 'B'],
['C', 'A', 'C'],
['C', 'B', 'A'],
['C', 'B', 'B'],
['C', 'B', 'C'],
['C', 'C', 'A'],
['C', 'C', 'B'],
['C', 'C', 'C'],
]);
const permutations4 = permutateWithRepetitions(['A', 'B', 'C', 'D']);
expect(permutations4.length).toBe(4 * 4 * 4 * 4);
testPermutateWithRepetitionsFn(permutateWithRepetitions);
});
});

View File

@ -0,0 +1,8 @@
import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive';
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
describe('permutateWithRepetitionsRecursive', () => {
it('should permutate string with repetition', () => {
testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive);
});
});

View File

@ -0,0 +1,51 @@
export default function testPermutateWithRepetitionsFn(fn) {
const permutations0 = fn([]);
expect(permutations0).toEqual([]);
const permutations1 = fn(['A']);
expect(permutations1).toEqual([
['A'],
]);
const permutations2 = fn(['A', 'B']);
expect(permutations2).toEqual([
['A', 'A'],
['A', 'B'],
['B', 'A'],
['B', 'B'],
]);
const permutations3 = fn(['A', 'B', 'C']);
expect(permutations3).toEqual([
['A', 'A', 'A'],
['A', 'A', 'B'],
['A', 'A', 'C'],
['A', 'B', 'A'],
['A', 'B', 'B'],
['A', 'B', 'C'],
['A', 'C', 'A'],
['A', 'C', 'B'],
['A', 'C', 'C'],
['B', 'A', 'A'],
['B', 'A', 'B'],
['B', 'A', 'C'],
['B', 'B', 'A'],
['B', 'B', 'B'],
['B', 'B', 'C'],
['B', 'C', 'A'],
['B', 'C', 'B'],
['B', 'C', 'C'],
['C', 'A', 'A'],
['C', 'A', 'B'],
['C', 'A', 'C'],
['C', 'B', 'A'],
['C', 'B', 'B'],
['C', 'B', 'C'],
['C', 'C', 'A'],
['C', 'C', 'B'],
['C', 'C', 'C'],
]);
const permutations4 = fn(['A', 'B', 'C', 'D']);
expect(permutations4.length).toBe(4 * 4 * 4 * 4);
}

View File

@ -0,0 +1,26 @@
/**
* @param {*[]} permutationOptions
* @return {*[]}
*/
export default function permutateWithRepetitionsRecursive(
options,
n = options.length || 0,
prefix = [],
perms = [],
) {
// If initial options are null or empty then return empty array
if (!options || !options.length) return [];
// If no more iterations then add current prefix to perms array
if (n === 0) {
perms.push(prefix);
return perms;
}
// Recursively find permutations and store in perms array
options.forEach((option) => {
permutateWithRepetitionsRecursive(options, n - 1, prefix.concat([option]), perms);
});
return perms;
}