【问题标题】:Reordering numbers重新排序数字
【发布时间】:2010-12-12 02:42:16
【问题描述】:

我有 1-62 范围内的数字 我希望能够“加密”它们,因此很难猜测它们是按某种顺序生成的。

所以,应该是一些映射,比如

1->35 2->19 3->61 ...

这样我就有了 1 对 1 的映射,100% 可逆。


我可以对映射进行硬编码,但我更喜欢数学解决方案,某种以数字为参数的公式,并产生 1-62 范围内的数字,并且不会生成重复项。这个公式有没有可能存在?


仅用于历史,验证脚本:

<?
  $test = array();

  $val = 37;
  for($i=0;$i<62;$i++)
  {
    if($test[($i*$val)%62])
    {
      print("Collision: $i ".$test[($i*$val)%62]."<br/>");
    }
    $test[($i*$val)%62] = $i;
    print("$i => ".(($i*$val)%62)."<br/>");
  }

?>

更新:

以下是由于这些答案而生成的 ID:

qpOLHk
NMb84H
aI740D
x5urn0
UsROKn
hPeb7K
EcByu7
1zYVRu
oWlieR
LjIFBe
8G52YB
v3splY
SqPMIl
fNc95I
Cazws5
ZxWTPs
mUjgcP
JhGDzc
6E30Wz

亲爱的 :-)

【问题讨论】:

    标签: math permutation shuffle random


    【解决方案1】:

    您可以将数字 1 到 62 放入一个数组中并打乱该数组(例如使用Fisher-Yates shuffle)。然后将数组的索引映射到该单元格的内容(但如果使用 0 索引数组,请注意非一错误)。

    为了使其具有确定性,请为随机数生成器使用特定的种子。

    编辑:一种计算成本较低(也更容易猜到)的映射是乘以某个常数,然后以 62 为模计算结果:

    result = (input * 37) % 62
    

    数字 37 只是一个例子。您可以使用 coprime 到 62 之间的任何数字 - 即除 31 之外的任何奇数。

    【讨论】:

    • 这适用于我正在考虑的硬编码。静态种子可以,但我担心处理太多,我需要一些简单的东西......
    • @BarsMonster:允许处理多少?您认为该算法的哪一部分过于昂贵?
    • 这将在解释语言中每秒执行 10'000 次。虽然我看到您的解决方案可能在性能方面很合适,但我真的很喜欢输出 = (input+35)%62 之类的东西,但更随机一些。
    • @BarsMonster:(input*37) % 62 怎么样?或pow(input, 37) % 62。后者可以通过重复平方和在每一步取模来快速计算。当然,加 1 使范围为 1-62 而不是 0-61。
    • 它给出重复,多个输入值相同的输出。
    【解决方案2】:

    与 Mark Byers 的评论一致。求x mod n 的倒数(例如,n=62)。

    x 成为区间[1, n] 中的输入整数。使用extended Euclidean algorithm 查找yt,这样xy + nt = 1 mod n。然后y = x^{-1} mod n

    【讨论】:

      【解决方案3】:

      【讨论】:

        【解决方案4】:

        使用RSA。它很容易实现(嗯,取决于语言),这里是worked example

        【讨论】:

        • 不幸的是,它的输出是以某个大数字为模的数字 => 我看不出它是如何将每个值映射到其他值而不在指定范围内重复的。
        • @BarsMonster:你是对的。我没有看到您也需要 1-62 的输出。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 2011-01-27
        • 2020-10-30
        相关资源
        最近更新 更多