0

I am trying to find the Rank of the given string in the list of possible permutations. I tried to come up with a solution that tries to find all possible permutations, assign a rank to them and then display it.

But this drastically reduces the performance when the length of the string keeps increasing. So was wondering if someone can think of an efficient solution for this problem..

function permute(str) {
    // Sort the string
    var arr = [];
    for (var i = 0; i < str.length; i++) arr.push(str[i]);
    var sortedString = arr.sort().join(''),
        // Length of the string
        length = str.length,
        used = [];
    // Create a boolean array for length of the string
    while (length--) used.push(false);
    // String buffer that holds the current string
    var out = '';
    // Call the function
    doPermute(sortedString, str, out, used, str.length, 0);
}
var count = 0;

function doPermute(inp, givenString, out, used, length, level) {
    // Only if length of the string equal to current level print it
    // That is permutation length is eqaul to string length
    if (level == length) {
        count++;
        //console.log('Perm :: ' + out + ' -- ' + count);
        if (out === givenString) {
            var pp = 'Rank of  :: ' + out + ' -- ' + count;
            $('div').append('<p>' + pp + '</p>');
        }
        return;
    }
    for (var i = 0; i < length; ++i) {
        // If variable used continue
        if (used[i]) continue;
        // Append the current char in loop
        out += inp[i];
        // set variable to true
        used[i] = true;
        // Call the function again
        doPermute(inp, givenString, out, used, length, level + 1);
        // Set it to false as the variable can be reused
        used[i] = false;
        // remove the last character of the buffer
        out = out.slice(0, out.length - 1)
    }
}

permute('dbcarf')

Fiddle

Sushanth --
  • 55,259
  • 9
  • 66
  • 105

2 Answers2

2

Sure: if input string is "cab". What is the lowest rank that a string starting with c could get?

c Note the strings that come before it.

abc
acb
bac
bca

So a string starting with c has minimum rank 5.This is just number of characters in input string that come lexicographically before c.(in order a,b,c,d,e,f...)So we have 2.Each word starting with a letter can have 2 words.
Next letter is "a"?
What is minimum rank that a word starting with "ca" can get?
5
Why?
"a" is the best way we can fill the second spot with the remaining letters.
And the same goes for third element "b".
So rank of "cab" is 5.

In general.(Assuming no duplicates, though this is not much harder)

var W; //input string
 var C[26];
 var rank = 1;
 for (var i = 0; i < W.length; i++) C[W[i] - 'a']++;
 for (var i = 0; i < W.length; i++) {
     //How many characters which are not used, that come before current character
     var count = 0;
     for (var j = 0; j < 26; j++) {
         if (j == (W[i] - 'a')) break;
         if (C[j] > 0) count++;
     }
     C[W[i] - 'a'] = 0;
     rank += count * fact(W.length - i - 1);
 }
Aravind
  • 3,169
  • 3
  • 23
  • 37
  • @Aravind.. This is really cool .. It is almost close to work with non repeated characters.. http://jsfiddle.net/QV5LF/3/ .. Except that the rank is being incremented by that amount even after the string is found.. – Sushanth -- Jul 11 '13 at 20:28
  • Check this: http://jsfiddle.net/QV5LF/7/ Edit:I had a small bug, start with int rank=1 and then change this line. rank += count * fact(W.length - i - 1); – Aravind Jul 12 '13 at 07:28
  • @Aravind.. that's cool.. Seems to have solved the problem.. How difficult would it be make it work with duplicate characters – Sushanth -- Jul 12 '13 at 17:00
  • @Sushanth--:If you are familiar with the mathematics of permuting n things of which a things are similar as n!/a!, then this is just a easy modification to deal with duplicated characters. – Aravind Jul 12 '13 at 17:07
  • I tried doing that but there was something wrong with the way i was calculating things.. So it was throwing it off.. Let me pass it on – Sushanth -- Jul 12 '13 at 17:14
  • If you continue to have problems with handling duplicate characters please post it as a separate question with code, and I will help you find the bug. – Aravind Jul 12 '13 at 17:23
  • Thanks for the solution arvind :) .. I have posted the question for duplicates in this post http://stackoverflow.com/questions/17620694/finding-the-rank-of-the-given-string-in-list-of-all-possible-permutations-with-d – Sushanth -- Jul 12 '13 at 17:31
0

There is an explanation in https://en.wikipedia.org/wiki/Permutation#Numbering_permutations of how to convert a permutation on n objects to a number in the range 0..n!-1 and it goes on to say that "Converting successive natural numbers to the factorial number system produces those sequences in lexicographic order (as is the case with any mixed radix number system), and further converting them to permutations preserves the lexicographic ordering, provided the Lehmer code interpretation is used" So I would try doing this number conversion and see if it produces something related to the rank that you need, by your definition.

mcdowella
  • 19,301
  • 2
  • 19
  • 25