Berechnung des Faktor-Ranges einer Permutation (N wähle K)

Ich habe kürzlich davon erfahrenCNS undF NSund da sie für mich so elegant aussehen, habe ich mich entschlossen, Methoden zu implementieren, um mit diesen Techniken Kombinationen und Permutationen zu generieren. Ich habe meine Konvertierungsmethode beendetn wähle k Kombinationen zu einem CSN-Rang und umgekehrt, aber ich stoße mit dem Kopf gegen die Wand und versuche, dasselbe zu tunn wähle k (eindeutige) Permutationen.

Dank an@Joshua ich habe dasranglos (FNS zu Permutation) Methode funktioniert:

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;
}

Dies ist mein aktueller Versuch einerRang (Umstellung auf FNS) Methode:

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;
}

Und dies sind die Hilfsfunktionen, die ich benutze:

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));
}

Das Problem ist,dasPr_Rank() Methode gibt nur den korrekten Rang zurück, wennn = k (Demo):

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

Ich habe mich anhand des Wikipedia-Artikels geführt, den ich oben verlinkt habedieser MSDN-ArtikelIch weiß, keiner von ihnen erwägt k-große Teilmengen, aber ich bin völlig im Dunkeln, wie eine solche Logik aussehen würde ...

Ich habe auch versucht, zu googeln und vorhandene Fragen / Antworten zu suchen, aber es ist noch nichts Relevantes aufgetaucht.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage