【问题标题】:Computing the Factoradic Rank of a Permutation (N choose K)计算置换的阶乘秩(N 选择 K)
【发布时间】:2012-06-23 19:49:43
【问题描述】:

我最近了解了CNSFNS,因为它们对我来说看起来很优雅,所以我决定尝试实现使用这些技术生成组合和排列的方法。我完成了从 n 选择 k 组合转换为 CSN 等级的方法,反之亦然,但我试图用 n 选择 k em>(唯一的)排列。

感谢@Joshua 我得到了 unranking(FNS 到排列)方法工作:

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

这是我目前对排名(排列为 FNS)方法的尝试:

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

这些是我正在使用的辅助函数:

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

问题是,Pr_Rank() 方法仅在 n = 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

我使用上面链接的 Wikipedia 文章和 this MSDN article 指导自己,我知道他们都不考虑 k 大小的子集,但我完全不知道这种逻辑会是什么样子......

我也尝试过谷歌搜索和搜索现有的问题/答案,但尚未找到相关的内容。

【问题讨论】:

    标签: php math permutation combinatorics base-conversion


    【解决方案1】:

    经过一夜好眠和笔和纸的一点帮助,我想通了。如果有人感兴趣:


    例如,第 42 个 5 选择 3 排列是 4-2-5,但如果您查看 Pr_Unrank(),其中 @987654323 @ 被调用时,您会注意到实际排列(按字典顺序)实际上是 4-2-5[-1-3],最后两个元素被丢弃,因此您最终只得到 k 元素。 p>

    这对于计算阶乘 (3-1-2[-0-0]) 的十进制表示非常重要:

    • 4-2-5 = (2! * 3) + (1! * 1) + (0! * 2) = 9
    • 4-2-5-1-3 = (4! * 3) + (3! * 1) + (2! * 2) + (1! * 0) + (0! * 0) = 82

    不过,82 不是正确答案。要得到它,我们必须将它除以以下结果:

    • Pr(5, 5) / Pr(5, 3) (=) (5 - 3)! = 120 / 60 = 2

    所以82 / 241,我需要做的就是添加1 以获得从1 开始的排名。


    Array // 5 choose 3 permutations
    (
        [1] => 1-2-3
        [2] => 1-2-4
        [3] => 1-2-5
        [4] => 1-3-2
        [5] => 1-3-4
        [6] => 1-3-5
        [7] => 1-4-2
        [8] => 1-4-3
        [9] => 1-4-5
        [10] => 1-5-2
        [11] => 1-5-3
        [12] => 1-5-4
        [13] => 2-1-3
        [14] => 2-1-4
        [15] => 2-1-5
        [16] => 2-3-1
        [17] => 2-3-4
        [18] => 2-3-5
        [19] => 2-4-1
        [20] => 2-4-3
        [21] => 2-4-5
        [22] => 2-5-1
        [23] => 2-5-3
        [24] => 2-5-4
        [25] => 3-1-2
        [26] => 3-1-4
        [27] => 3-1-5
        [28] => 3-2-1
        [29] => 3-2-4
        [30] => 3-2-5
        [31] => 3-4-1
        [32] => 3-4-2
        [33] => 3-4-5
        [34] => 3-5-1
        [35] => 3-5-2
        [36] => 3-5-4
        [37] => 4-1-2
        [38] => 4-1-3
        [39] => 4-1-5
        [40] => 4-2-1
        [41] => 4-2-3
        [42] => 4-2-5
        [43] => 4-3-1
        [44] => 4-3-2
        [45] => 4-3-5
        [46] => 4-5-1
        [47] => 4-5-2
        [48] => 4-5-3
        [49] => 5-1-2
        [50] => 5-1-3
        [51] => 5-1-4
        [52] => 5-2-1
        [53] => 5-2-3
        [54] => 5-2-4
        [55] => 5-3-1
        [56] => 5-3-2
        [57] => 5-3-4
        [58] => 5-4-1
        [59] => 5-4-2
        [60] => 5-4-3
    )
    

    【讨论】:

    • 很高兴你能解决这个问题!我只是没有时间研究它......
    猜你喜欢
    • 2013-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 2022-01-17
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多