To randomly permute a list one has to select one of $n!$ possibilities, which quickly goes outside of the capabilities of conventional PRNGs. Even Mersenne Twister fails with a list of length greater than 2080 entries, and probably fails much sooner in practice because there's no guarantee that its state is used in a way that eliminates duplicate outcomes.
So, in the process of designing an algorithm to shuffle a list from inadequate state, and designing this as a library function (rather than as an application-specific solution), what would normally be the design criteria that should be met (or maximised or minimised) first, and what compromises are likely to be the most benign?
This is in the general case. Obviously some applications are oblivious to problems that others could turn into a catastrophic failure.
In other words, how do you evaluate the quality of a shuffle when you know in advance it must be imperfect (in the same way as you know a PRNG is imperfect)?
The reason I ask, and as an example of the sorts of things I'd like to detect, is that during development of a shuffle algorithm I got a couple of obviously-bad results but wasn't sure what the best way to formalise them as tests would be.
An acutely problematic shuffle, for example would be:
static uint32_t n; // number of elements in list to shuffle
static uint32_t m; // n rounded up to a power-of-two, minus one
static uint32_t state; // set to a random value to randomise order
void shuffle_seed(uint32_t seed) {
state = s;
}
uint32_t next_index(void) {
do {
seed = (state * 1103515245 + 12345) & m;
} while (state >= n);
return state;
}
You can call this function n
times and be guaranteed n
unique results between 0
and n
... so it's a permutation; but when you compare the result for one seed to that for another you find that they're the same sequence starting at different points. Also, every second index is odd and the others even.
Another, slightly more advanced design gave partial substring matches rather than the whole thing.
If you can choose only $n$ or $n^k$ (for smallish $k$) different permutations out of $n!$, ones containing similar sub-strings are probably the ones you'd want to eliminate first. I expect there are a variety of other kinds of poor choice that I haven't thought of.