So I have this code now, and in input I have in ascending order my name\'s letters \"ahimrsu\". I need to show up the right number for \"mariush\" from all combinations whic
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:
permute
of the type [a] -> [[a]]
(i.e. given a list of a
s it returns a list of permutations of the input).[]
) an an input, the output is an empty list of permutations ([[]]
).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:
1
and list [2, 3]
.
[2, 3]
.
2
and list [3]
.
[3]
.
3
and list []
.
[]
which is [[]]
.3
to the beginning of each permutation.[[3]]
.2
to the beginning of each permutation.[[2, 3]]
.3
and list [[2]]
.
[2]
.
2
and list []
.
[]
which is [[]]
.2
to the beginning of each permutation.[[2]]
.3
to the beginning of each permutation.[[3, 2]]
.[[2, 3], [3, 2]]
.1
to the beginning of each permutation.[[1, 2, 3], [1, 3, 2]]
.2
and list [1, 3]
.3
and list [1, 2]
.[[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.
Well, 'mariush' is actually permutation 2220 if we are using your ordering scheme:
/*jslint white: true*/
var perm = function(s){
'use strict';
if(s.length === 1){
return [s];
}
// For each character c in s, generate the permuations p of all
// the other letters in s, prefixed with c.
return [].reduce.call(s, function(p,c,i){ // permutations, char, index
var other = s.slice(0,i) + s.slice(i+1);
return p.concat(perm(other).map(function(oneperm){
return c + oneperm;
}));
}, []);
};
alert(perm('ahimrsu').indexOf('mariush') + 1); // 2220
Algorithm for string permutation will be a little bit more complicated with recursive step (it's possible to code it without recursion though).
The next javascript implementation is based on the description of the algorithm from this answer:
- Remove the first letter
- Find all the permutations of the remaining letters (recursive step)
- Reinsert the letter that was removed in every possible location.
Implementation then something like this:
function permutation(str) {
if (str.length == 1) {
return [str];
}
var first = str[0], // Step #1
perms = permutation(str.slice(1)), // Step #2
result = [];
// Step #3
for (var i = 0; i < perms.length; i++) {
for (var j = 0; j <= perms[i].length; j++) {
result.push( perms[i].slice(0, j) + first + perms[i].slice(j) );
}
}
return result;
}
console.log(permutation('ahimrsu'));
Above implementation gives 5040 combinations, which seems to be correct, since 7! == 5040 (number of permutations is a factorial of the number of chars).
Now when you have all possible permutations array you can easily find specific string occurrence:
var combinations = permutation('ahimrsu');
var index = combinations.indexOf('mariush'); // Index of the "mariush"
alert('"mariush" is the ' + (index + 1) + 'th permutation of "ahimrsu".');