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
One way to do it would be
p
larger than N
, preferably not much larger.g
modulo p
, that is, a number 1 < g < p
such that g^k ≡ 1 (mod p)
if and only if k
is a multiple of p-1
.g^k (mod p)
for k = 1, 2, ...
, ignoring the values that are larger than N
.For every prime p
, there are φ(p-1)
primitive roots of unity, so it works. However, it may take a while to find one. Finding a suitable prime is much easier in general.
For finding a primitive root, I know nothing substantially better than trial and error, but one can increase the probability of a fast find by choosing the prime p
appropriately.
Since the number of primitive roots is φ(p-1)
, if one randomly chooses r
in the range from 1 to p-1
, the expected number of tries until one finds a primitive root is (p-1)/φ(p-1)
, hence one should choose p
so that φ(p-1)
is relatively large, that means that p-1
must have few distinct prime divisors (and preferably only large ones, except for the factor 2).
Instead of randomly choosing, one can also try in sequence whether 2, 3, 5, 6, 7, 10, ...
is a primitive root, of course skipping perfect powers (or not, they are in general quickly eliminated), that should not affect the number of tries needed greatly.
So it boils down to checking whether a number x
is a primitive root modulo p
. If p-1 = q^a * r^b * s^c * ...
with distinct primes q, r, s, ...
, x
is a primitive root if and only if
x^((p-1)/q) % p != 1
x^((p-1)/r) % p != 1
x^((p-1)/s) % p != 1
...
thus one needs a decent modular exponentiation (exponentiation by repeated squaring lends itself well for that, reducing by the modulus on each step). And a good method to find the prime factor decomposition of p-1
. Note, however, that even naive trial division would be only O(√p), while the generation of the permutation is Θ(p), so it's not paramount that the factorisation is optimal.