Pagina's

2014/01/23

The kth Permutation

/*

It is based on:

    "Using Permutations in .Net for Improved System Security"

Factoradics are used to find the kth permutation of order n.

*/

class Permutation
{
    private static uint[] kth_perm(uint k, uint n)  //  k=0,n=3 ==> {0,1,2}
    {                                               //  k=1,n=3 ==> {0,2,1}
        if (n == 0) return new uint[] { };
        uint[] perm = new uint[n++];
        uint[] fdic = new uint[n];                  //  in factoradic form, no factorials!
        uint i = 1, d, m = n - 1;
        do
        {
            d = k / i;
            fdic[m--] = k - d * i++;
            k = d;
        }
        while (m != ~0u);
        for (k = n-- - 2; k != ~0u; k--)
        {
            m = perm[k++] = fdic[k];
            for (i = k--; i < n; i++) if (perm[i] >= m) perm[i]++;
        }
        return perm;
    }

    private static uint[] next_perm(uint[] perm)    //  {0,1,2} ==> {0,2,1}
    {
        int len = perm.Length - 1;
        if (len <= 0) return perm;
        int i = len;
        while (i > 0 && perm[i--] <= perm[i]) ;
        uint swap = perm[i];
        int j = len;
        while (j > 0 && perm[j] <= swap) j--;
        if (j == 0)
            do
            {
                swap = perm[len];
                perm[len--] = perm[j];
                perm[j++] = swap;
            }
            while (j < len);
        else
        {
            perm[i++] = perm[j];
            perm[j] = swap;
            while (len > i)
            {
                swap = perm[len];
                perm[len--] = perm[i];
                perm[i++] = swap;
            }
        }
        return perm;
    }

    static void Main()
    {
        uint[] perm = kth_perm(999999, 10);  //            {2,7,8,3,9,1,5,4,6,0}
        perm = next_perm(perm);              //            {2,7,8,3,9,1,5,6,0,4}
        perm = new uint[] { 3, 1, 3, 1 };    //  {3,1,3,1}
        perm = next_perm(perm);              //  {3,3,1,1}
        perm = next_perm(perm);              //  {1,1,3,3}
        perm = next_perm(perm);              //  {1,3,1,3}
        perm = next_perm(perm);              //  {1,3,3,1}
        perm = next_perm(perm);              //  {3,1,1,3}
        perm = next_perm(perm);              //  {3,1,3,1}
    }
}

No comments:

Post a Comment