mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 07:01:18 +08:00
Add recursive way of generating permutations with repetitions.
This commit is contained in:
parent
b0c55ec817
commit
19f4cc70d3
@ -1,8 +1,55 @@
|
||||
import permutateWithRepetitions from '../permutateWithRepetitions';
|
||||
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
|
||||
|
||||
describe('permutateWithRepetitions', () => {
|
||||
it('should permutate string with repetition', () => {
|
||||
testPermutateWithRepetitionsFn(permutateWithRepetitions);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,55 @@
|
||||
import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive';
|
||||
import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn';
|
||||
|
||||
describe('permutateWithRepetitionsRecursive', () => {
|
||||
it('should permutate string with repetition', () => {
|
||||
testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive);
|
||||
const permutations0 = permutateWithRepetitionsRecursive([]);
|
||||
expect(permutations0).toEqual([]);
|
||||
|
||||
const permutations1 = permutateWithRepetitionsRecursive(['A']);
|
||||
expect(permutations1).toEqual([
|
||||
['A'],
|
||||
]);
|
||||
|
||||
const permutations2 = permutateWithRepetitionsRecursive(['A', 'B']);
|
||||
expect(permutations2).toEqual([
|
||||
['A', 'A'],
|
||||
['A', 'B'],
|
||||
['B', 'A'],
|
||||
['B', 'B'],
|
||||
]);
|
||||
|
||||
const permutations3 = permutateWithRepetitionsRecursive(['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 = permutateWithRepetitionsRecursive(['A', 'B', 'C', 'D']);
|
||||
expect(permutations4.length).toBe(4 * 4 * 4 * 4);
|
||||
});
|
||||
});
|
||||
|
@ -1,51 +0,0 @@
|
||||
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);
|
||||
}
|
@ -1,26 +1,37 @@
|
||||
/**
|
||||
* @param {*[]} permutationOptions
|
||||
* @param {number} permutationLength
|
||||
* @param {*[]} currentPermutation
|
||||
* @param {*[][]} permutations
|
||||
* @return {*[]}
|
||||
*/
|
||||
export default function permutateWithRepetitionsRecursive(
|
||||
options,
|
||||
n = options.length || 0,
|
||||
prefix = [],
|
||||
perms = [],
|
||||
permutationOptions,
|
||||
permutationLength = permutationOptions.length || 0,
|
||||
currentPermutation = [],
|
||||
permutations = [],
|
||||
) {
|
||||
// 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;
|
||||
// If initial options are null or empty then return empty array.
|
||||
if (!permutationOptions || !permutationOptions.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Recursively find permutations and store in perms array
|
||||
options.forEach((option) => {
|
||||
permutateWithRepetitionsRecursive(options, n - 1, prefix.concat([option]), perms);
|
||||
// If no more iterations required then add current permutation to permutations array.
|
||||
if (permutationLength === 0) {
|
||||
permutations.push(currentPermutation);
|
||||
|
||||
return permutations;
|
||||
}
|
||||
|
||||
// Recursively find permutations and store in permutations array.
|
||||
permutationOptions.forEach((permutationOption) => {
|
||||
permutateWithRepetitionsRecursive(
|
||||
permutationOptions,
|
||||
permutationLength - 1,
|
||||
currentPermutation.concat([permutationOption]),
|
||||
permutations,
|
||||
);
|
||||
});
|
||||
|
||||
return perms;
|
||||
return permutations;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user