Obliczanie racji czynnikowej permutacji (N wybierz K)

Ostatnio dowiedziałem się oCNS iFNSi ponieważ wyglądają dla mnie tak elegancko, postanowiłem spróbować i zaimplementować metody generowania kombinacji i permutacji przy użyciu tych technik. Skończyłem metodę konwersji zn wybierz k kombinacje do rangi CSN i odwrotnie, ale uderzam głową o ścianę, próbując zrobić to samon wybierz k (unikalne) permutacje.

Dzięki@Joshua mamunranking (FNS do permutacji) działająca metoda:

function Pr_Unrank($n, $k, $rank) { // rank starts at 1
    if ($n >= $k) {
        if (($rank > 0) && ($rank <= Pr($n, $k))) {
            $rank--;
            $result = array();
            $factoriadic = array();

            for ($i = 1; $i <= ($n - $k); ++$i) {
                $rank *= $i;
            }

            for ($j = 1; $j <= $n; ++$j) {
                $factoriadic[$n - $j] = ($rank % $j) + 1; $rank /= $j;
            }

            for ($i = $n - 1; $i >= 0; --$i) {
                $result[$i] = $factoriadic[$i];

                for ($j = $i + 1; $j < $n; ++$j) {
                    if ($result[$j] >= $result[$i]) {
                        ++$result[$j];
                    }
                }
            }

            return array_reverse(array_slice($result, 0 - $k));
        }
    }

    return false;
}

To jest moja obecna próbazaszeregowanie (permutacja do FNS) metoda:

function Pr_Rank($n, $k, $permutation) {
    if ($n >= $k) {
        $result = range(1, $n);
        $factoriadic = array();

        foreach ($permutation as $key => $value) {
            $factoriadic[$k - $key - 1] = array_search($value, $result);
            array_splice($result, $factoriadic[$k - $key - 1], 1);
        }

        $result = 1;

        foreach (array_filter($factoriadic) as $key => $value) {
            $result += F($key) * $value;
        }

        return $result;
    }

    return false;
}

A to są funkcje pomocnicze, których używam:

function F($n) { // Factorial
    return array_product(range($n, 1));
}

function Pr($n, $k) { // Permutations (without Repetitions)
    return array_product(range($n - $k + 1, $n));
}

Problemem jest,Pr_Rank() metoda zwraca właściwą pozycję tylko wtedy, gdyn = k (próbny):

var_dump(Pr_Rank(5, 2, Pr_Unrank(5, 2, 10))); // 3, should be 10
var_dump(Pr_Rank(5, 3, Pr_Unrank(5, 3, 10))); // 4, should be 10
var_dump(Pr_Rank(5, 5, Pr_Unrank(5, 5, 10))); // 10, it's correct

Poprowadziłem się za pomocą artykułu z Wikipedii, który umieściłem powyżej iten artykuł MSDN, Wiem, że żadna z nich nie rozważa podzbiorów wielkości k, ale jestem całkowicie w ciemności, jak wyglądałaby taka logika ...

Spróbowałem również Google i przeszukałem istniejące pytania / odpowiedzi, ale nic jeszcze nie wyszło.

questionAnswers(1)

yourAnswerToTheQuestion