I need to build an in-place pseudo-random number generator with an adjustable period. In addition, there must be no collisions within one period. That is, the following must return true:
// prng is "generated" at run-time
// (though a by-hand solution would work)
bool test(func prng, int period) {
int seed = 0; // Any number should work
int cur = seed;
for (int i = 0; i <= period; ++i) {
cur = prng(cur);
if (cur == seed) {
if (i == period) {
// We hit our period on target
return true;
}
// Period too low (we hit our seed already!)
return false;
}
}
// Period too high
return false;
}
(Example is pseudocode; an answer in any commonly readable language (C++, Python, Haskell, etc.) is acceptable.)
The PRNG must not depend on mutable static state when generating the numbers. That is, I can't have a large table of already-returned numbers or something like that. It should only rely on the given input for generating the next term.
The algorithm does not have to be cryptographically strong (of course), or "strongly" random. However, x % period
is not acceptable; it has to be at least somewhat random.
I have looked into linear congruential generators, but that seems to be the wrong path to take for my specific constraints.
(Brute-forcing is not an option, unless it's relatively quick (a few seconds).)