繁体   English   中英

如何使用可逆种子制作所有可能的列表组合?

[英]How can I make all possible list combinations using reversible seeds?

我想要一个由 100 个项目组成的列表,每个项目的值都在 0-31 之间。 然后我希望能够获取这些列表之一,并知道随机生成该确切列表所需的种子/输入。

使用一些合适的线性同余生成器:

您可以使用 Pierre L'Ecuyer 的这篇研究论文:

Tables_of_linear_congruential_generators_of_different_sizes_and_good_lattice_structure

本文给出了(相当伪随机的) LCG示例的 2 模的最低幂是 2 30 ,接近 10 亿。 见论文表 4。 只需选择其中一个 LCG,说:

u n+1 = ((116646453 * u n ) + 5437) mod 2 30

您的每个项目正好是 5 位宽。 如果您决定将项目 6 x 6 分组,则每个的宽度正好为 30 位,因此可以视为此模 2 30 LCG 的一种状态。

从最初的 6 个项目组开始,LCG 的一个步骤将生成下一组,即接下来的 6 个项目。 该论文告诉您,该系列总体上看起来相当随机。

因此,您可以将前 6 个项目视为您的“种子”,因为您可以从最左边的 6 个项目重构整个列表。

即使假设为了混淆起见,您在种子之后开始列表的可见部分,您仍然只有大约十亿个可能的种子需要担心。 通过模拟每个可能的种子的 LCG 并与实际列表进行比较,任何体面的计算机都可以在几秒钟内通过蛮力找到左隐藏的种子。

示例 Python 代码:

可以从创建一个类开始,给定一个种子,提供 0 到 31 之间的无限系列项目:

class LEcuyer30:
   def  __init__ (self, seed):
       self.seed      = seed & ((1 << 30) - 1)
       self.currGroup = self.seed
       self.itemCount = 6

   def __toNextGroup(self):
       nextGroup = ((116646453 * self.currGroup) + 5437) % (1 << 30)
       self.currGroup = nextGroup
       self.itemCount = 6

   def  getItem(self):
       if (self.itemCount <= 0):
           self.__toNextGroup()

       # extract 5 bits:
       word = self.currGroup >> (5 * (self.itemCount - 1))
       self.itemCount -= 1
       return (word & 31)

测试代码:

我们可以创建一个包含 20 个项目的序列并打印它:

# Main program:

randomSeed = 514703103
rng = LEcuyer30(randomSeed)

itemList = []
for k in range(20):
    item = rng.getItem()
    itemList.append(item)

print("itemList = %s" % itemList)

程序输出:

itemList = [15, 10, 27, 15, 23, 31, 1, 10, 5, 15, 16, 8, 4, 16, 24, 31, 7, 5, 8, 19]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM