mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
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:
parent
8d3f83cfb7
commit
b0c55ec817
@ -1,55 +1,8 @@
|
|||||||
import permutateWithRepetitions from '../permutateWithRepetitions';
|
import permutateWithRepetitions from '../permutateWithRepetitions';
|
||||||
|
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
|
||||||
|
|
||||||
describe('permutateWithRepetitions', () => {
|
describe('permutateWithRepetitions', () => {
|
||||||
it('should permutate string with repetition', () => {
|
it('should permutate string with repetition', () => {
|
||||||
const permutations0 = permutateWithRepetitions([]);
|
testPermutateWithRepetitionsFn(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);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive';
|
||||||
|
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
|
||||||
|
|
||||||
|
describe('permutateWithRepetitionsRecursive', () => {
|
||||||
|
it('should permutate string with repetition', () => {
|
||||||
|
testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive);
|
||||||
|
});
|
||||||
|
});
|
@ -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);
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user