This is my solution from the following answer: https://stackoverflow.com/a/18879232/783743
var permute = (function () {
return permute;
function permute(list) {
return list.length ?
list.reduce(permutate, []) :
[[]];
}
function permutate(permutations, item, index, list) {
return permutations.concat(permute(
list.slice(0, index).concat(
list.slice(index + 1)))
.map(concat, [item]));
}
function concat(list) {
return this.concat(list);
}
}());
You can use the permute
function to find all the permutations of an array:
var array = "ahimrsu".split("");
var permutations = permute(array).map(join);
var index = permutations.indexOf("maruish");
function join(array) {
return array.join("");
}
The algorithm is very simple to understand:
- We want a function
permute
of the type [a] -> [[a]]
(i.e. given a list of a
s it returns a list of permutations of the input).
- Given the empty list (
[]
) an an input, the output is an empty list of permutations ([[]]
).
- Otherwise for every element:
- We remove the element from the list.
- We recursively find the permutations of the remaining elements.
- We add the element we removed to the beginning of every permutation.
For example, suppose we want to find the permutation of the array [1, 2, 3]
:
1. permute([1, 2, 3]) === [1, 2, 3].reduce(permutate, [])
1. permutate([], 1, 0, [1, 2, 3])
1. permute([2, 3]) === [2, 3].reduce(permutate, [])
1. permutate([], 2, 0, [2, 3])
1. permute([3]) === [3].reduce(permutate, [])
1. permutate([], 3, 0, [3])
1. permute([]) === [[]]
2. [[]].map(concat, [3]) === [[3]]
3. [].concat([[3]]) === [[3]]
2. [[3]].map(concat, [2]) === [[2, 3]]
3. [].concat([[2, 3]]) === [[2, 3]]
2. permutate([[2, 3]], 3, 1, [2, 3])
1. permute([2]) === [2].reduce(permutate, [])
1. permutate([], 2, 0, [2])
1. permute([]) === [[]]
2. [[]].map(concat, [2]) === [[2]]
3. [].concat([[2]]) === [[2]]
2. [[2]].map(concat, [3]) === [[3, 2]]
3. [[2, 3]].concat([[3, 2]]) === [[2, 3], [3, 2]]
2. [[2, 3], [3, 2]].map(concat, [1]) === [[1, 2, 3], [1, 3, 2]]
3. [].concat([[1, 2, 3], [1, 3, 2]]) === [[1, 2, 3], [1, 3, 2]]
2. permutate([[1, 2, 3], [1, 3, 2]], 2, 1, [1, 2, 3])
1. permute([1, 3]) === [1, 3].reduce(permutate, [])
2. [[1, 3], [3, 1]].map(concat, [2]) === [[2, 1, 3], [2, 3, 1]]
3. [[1, 2, 3], [1, 3, 2]].concat([[2, 1, 3], [2, 3, 1]])
3. permutate([[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1]], 3, 2, [1, 2, 3])
1. permute([1, 2]) === [1, 2].reduce(permutate, [])
2. [[1, 2], [2, 1]].map(concat, [3]) === [[3, 1, 2], [3, 2, 1]]
3. [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1]].concat([[3, 1, 2], [3, 2, 1]])
Old explanation:
- First we remove the first element of the list. Hence we have item
1
and list [2, 3]
.
- Next we find the permutations of
[2, 3]
.
- We remove the first element. Hence we have item
2
and list [3]
.
- Next we find the permutations of
[3]
.
- We remove the first element. Hence we have item
3
and list []
.
- Next we find the permutations of
[]
which is [[]]
.
- We add
3
to the beginning of each permutation.
- The result is
[[3]]
.
- We add
2
to the beginning of each permutation.
- The result is
[[2, 3]]
.
- We remove the second element. Hence we have item
3
and list [[2]]
.
- Next we find the permutations of
[2]
.
- We remove the first element. Hence we have item
2
and list []
.
- Next we find the permutations of
[]
which is [[]]
.
- We add
2
to the beginning of each permutation.
- The result is
[[2]]
.
- We add
3
to the beginning of each permutation.
- The result is
[[3, 2]]
.
- We combine the two two lists.
- The result is
[[2, 3], [3, 2]]
.
- We add
1
to the beginning of each permutation.
- The result is
[[1, 2, 3], [1, 3, 2]]
.
- Same for the second element: item
2
and list [1, 3]
.
- Same for the third element: item
3
and list [1, 2]
.
- We combine the three lists.
- The result is
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
.
See the demo:
var permute = (function () {
return permute;
function permute(list) {
return list.length ?
list.reduce(permutate, []) :
[[]];
}
function permutate(permutations, item, index, list) {
return permutations.concat(permute(
list.slice(0, index).concat(
list.slice(index + 1)))
.map(concat, [item]));
}
function concat(list) {
return this.concat(list);
}
}());
var array = "ahimrsu".split("");
var permutations = permute(array).map(join);
var index = permutations.indexOf("maruish");
alert("maruish is the " + (index + 1) + "th permutation of ahimrsu.");
function join(array) {
return array.join("");
}
Hope that helps.