How to generate a random sequence (permutation) of a finite sequence.
Fisher–Yates shuffle
The original form was described by Ronald Fisher and Frank Yates:
- Write down the numbers from 1 through N.
- Pick a random number k between one and the number of un-struck numbers remaining (inclusive).
- Counting from the low end, strike out the kth number not yet struck out, and write it down at the end of a separate list.
- Repeat from step 2 until all the numbers have been struck out.
- The sequence of numbers written down in step 3 is now a random permutation of the original numbers
The modern version of the Fisher–Yates shuffle, designed for computer use, was introduced by Richard Durstenfeld in 1964 and popularized by Donald E. Knuth in The Art of Computer Programming as “Algorithm P (Shuffling)”.
|
|
(clang’s libc++ uses this idea, see /usr/include/c++/v1/algorithm
on your computer or github: llvm-project)
You can easily write a equivalent left to right version of this.
|
|
The “inside-out” shuffle
(gcc’s libstdc++ uses this, see /usr/include/c++/<gcc version>/bits/stl_algo.h
on your computer or github: gcc-mirror)
To simultaneously initialize and shuffle an array, use this:
|
|
At any loop, items[0:i]
is a shuffle of items[0:i]
, you don’t even need to know the value of n in advance.
The correctness of the inside-out shuffle can be proved by induction.