I have an array of things (conceptually a set, but let’s implement as an array), say [A, B, C, D, E, F].
I need an algorithm that can pseudo-randomly pick an item from the array such that no item will be picked twice within x iterations.
That is, if x is 3 for this array, this would be ok: F, C, B, D, F, E, A, B,…
This would not be ok: F, C, D, C, …
Other than this constraint, the selections should be as random as possible. (For instance, simply shuffling the array and selecting within copies of it is not acceptable.)
Ideally, this would achieved without having to record all the previous picks.
So the function would have a structure like:
function pick(options, minspacing, iteration) {...}
3
Answers
This seems to fit the bill:
For each iteration
i
, ifi<x
, then:j
in [i,N)i!=j
, then swapA[i]
withA[j]
A[i]
For all other iterations, where
i>=x
:j
in [x, N)A[j]
withA[i%x]
A[i%x]
. It will not be swapped back into the choosable range until afterx
more iterations.This code choses a pseudo-random index from a range >=2 without replacement up to an arbitrary non-repetition length >=1 . You can then use the index to dereference any array of values of the same length [A,B,C … ].
Incorporating this as a closure you have a generator of unlimited choice iterations.
My approach to handle this problem (as per my understanding of the problem) would be like:
Pseudocode:
CODE IMplementation:
Hope it helps.