Create a random permutation of 1..N in constant space

前端 未结 6 727
旧巷少年郎
旧巷少年郎 2020-11-30 04:30

I am looking to enumerate a random permutation of the numbers 1..N in fixed space. This means that I cannot store all numbers in a list. The reason for that is that N can be

6条回答
  •  一整个雨季
    2020-11-30 04:52

    Consider the prime 3. To fully express all possible outputs, think of it this way...

    bias + step mod prime
    

    The bias is just an offset bias. step is an accumulator (if it's 1 for example, it would just be 0, 1, 2 in sequence, while 2 would result in 0, 2, 4) and prime is the prime number we want to generate the permutations against.

    For example. A simple sequence of 0, 1, 2 would be...

    0 + 0 mod 3 = 0
    0 + 1 mod 3 = 1
    0 + 2 mod 3 = 2
    

    Modifying a couple of those variables for a second, we'll take bias of 1 and step of 2 (just for illustration)...

    1 + 2 mod 3 = 0
    1 + 4 mod 3 = 2
    1 + 6 mod 3 = 1
    

    You'll note that we produced an entirely different sequence. No number within the set repeats itself and all numbers are represented (it's bijective). Each unique combination of offset and bias will result in one of prime! possible permutations of the set. In the case of a prime of 3 you'll see that there are 6 different possible permuations:

    0,1,2
    0,2,1
    1,0,2
    1,2,0
    2,0,1
    2,1,0
    

    If you do the math on the variables above you'll not that it results in the same information requirements...

    1/3! = 1/6 = 1.66..
    

    ... vs...

    1/3 (bias) * 1/2 (step) => 1/6 = 1.66..
    

    Restrictions are simple, bias must be within 0..P-1 and step must be within 1..P-1 (I have been functionally just been using 0..P-2 and adding 1 on arithmetic in my own work). Other than that, it works with all prime numbers no matter how large and will permutate all possible unique sets of them without the need for memory beyond a couple of integers (each technically requiring slightly less bits than the prime itself).

    Note carefully that this generator is not meant to be used to generate sets that are not prime in number. It's entirely possible to do so, but not recommended for security sensitive purposes as it would introduce a timing attack.

    That said, if you would like to use this method to generate a set sequence that is not a prime, you have two choices.

    First (and the simplest/cheapest), pick the prime number just larger than the set size you're looking for and have your generator simply discard anything that doesn't belong. Once more, danger, this is a very bad idea if this is a security sensitive application.

    Second (by far the most complicated and costly), you can recognize that all numbers are composed of prime numbers and create multiple generators that then produce a product for each element in the set. In other words, an n of 6 would involve all possible prime generators that could match 6 (in this case, 2 and 3), multiplied in sequence. This is both expensive (although mathematically more elegant) as well as also introducing a timing attack so it's even less recommended.

    Lastly, if you need a generator for bias and or step... why don't you use another of the same family :). Suddenly you're extremely close to creating true simple-random-samples (which is not easy usually).

提交回复
热议问题