ETHproductions / japt

Japt 1.4.5, the other JavaScript golfing language
http://ethproductions.github.io/japt
75 stars 10 forks source link

Add a method to get the N-th lexicographical permutation #46

Open Etheryte opened 6 years ago

Etheryte commented 6 years ago

In some cases, it's favorable to get a single permutation instead of finding all the permutations, especially for large N.

I've written a sample implementation based on this article:

// Input: Number
// Output: Array of the factoradic representation digits of the input
function factoradic(n) {
    var f = [];
    for (var i = 1; n > 0; n = Math.floor(n / i++)) {
        f.push(n % i);
    }
    return f.reverse();
}

// Input: Array, Number
// Output: N-th lexographical permutation of the input array
function nthPermutation(a, n) {
    var p = [];
    var fac = factoradic(n);
    var copy = a.slice();
    for (var i = 0; i < fac.length; i++) {
        p.push(copy.splice(fac[i], 1)[0]);
    }
    return p;
}
ETHproductions commented 6 years ago

Great suggestion. Thanks to Jelly, I've wanted to do this for a while, so thanks for putting together an implementation. A small bug: when n is less than factorial(a.length - 1), the output doesn't contain all items of the input. The best way I think we can fix that is by adding a second argument to the factoradic function that determines the length of the permutation. So:

// Input: Number, Number
// Output: Array of the factoradic representation digits of the input
function factoradic(n, l) {
    var f = [];
    for (var i = 1; l > 0; l--) {
        f.push(n % i);
        n = Math.floor(n / i++);
    }
    return f.reverse();
}

// Input: Array, Number
// Output: N-th lexographical permutation of the input array
function nthPermutation(a, n) {
    var p = [];
    var fac = factoradic(n, a.length);
    var copy = a.slice();
    for (var i = 0; i < fac.length; i++) {
        p.push(copy.splice(fac[i], 1)[0]);
    }
    return p;
}