给定范围内的所有数字,但随机顺序

时间:2017-06-29 07:29:37

标签: math random range theory generated

假设我想以随机顺序生成1-1000的所有整数。但...

  • 一旦
  • 再生成一个数字
  • 不存储数组,列出所有可能数字的数据
  • 不存储已生成的数字。
  • 最后没有遗漏任何数字。

我认为这应该是不可能的,但也许我只是没有考虑正确的解决方案。

我想在C#中使用它,但我对approche然后实际的实现更感兴趣。

2 个答案:

答案 0 :(得分:3)

加密。加密是两组之间的一对一映射。如果两个集合相同,则它是由加密密钥指定的排列。写/找到将{0,1000}映射到自身的加密。阅读Format Preserving Encryption(FPE)以帮助您。

要生成随机顺序,只需按顺序加密数字0,1,2 .......您不需要存储它们,只需跟踪您在列表中的位置。

从实际的角度来看,{0,1023}中的数字会更容易处理,因为它是一个块大小为10位的块密码,你可以编写一个简单的Feistel cipher来生成你的号码。你可能想要这样做,只需重新加密1000以上的数字 - FPE的循环步行方法。

答案 1 :(得分:2)

如果随机性不是主要问题,您可以使用linear congruential generator。由于当模数为素数时,LCG不会产生最大长度序列,因此您需要选择较大的模数(2的最大幂次是明显的选择)并跳过所需范围之外的任何值。 / p>

我担心C#不是我的事,但希望以下Python不言自明。如果要在非常小的范围内生成序列,则需要进行一些调整:

# randint(a, b) returns a random integer in the range (a..b) (inclusive)
from random import randint

def lcg_params(u, v):
    # Generate parameters for an LCG that produces a maximal length sequence
    # of numbers in the range (u..v)
    diff = v - u
    if diff < 4:
         raise ValueError("Sorry, range must be at least 4.")
    m = 2 ** diff.bit_length()              # Modulus
    a = (randint(1, (m >> 2) - 1) * 4) + 1  # Random odd integer, (a-1) divisible by 4
    c = randint(3, m) | 1                   # Any odd integer will do
    return (m, a, c, u, diff + 1)

def generate_pseudorandom_sequence(rmin, rmax):
    (m, a, c, offset, seqlength) = lcg_params(rmin, rmax)
    x = 1         # Start with a seed value of 1
    result = []   # Create empty list for output values
    for i in range(seqlength):
        # To generate numbers on the fly without storing them in an array,
        # just run the following while loop to fetch a new number
        while True:
            x = (x * a + c) % m             # Iterate LCG until we get a value in the
            if x < seqlength: break         # required range
        result.append(x + offset)           # Add this value to the list
    return result

实施例

>>> generate_pseudorandom_sequence(1, 20)
[4, 6, 8, 1, 10, 3, 12, 5, 14, 7, 16, 9, 18, 11, 20, 13, 15, 17, 19, 2]