The Fisher–Yates Random Shuffle Algorithm


Given an array, we want to shuffle it (to make it random), so that every possible random solution gets evenly-distributely possibility. One may quickly write a solution like this, which seems correct, but it is not:

1
2
3
4
5
void shuffleArray(vector<int> &array) {
  for (int i = 0; i < array.size(); ++ i) {
    swap(array[i], (rand % array.size()));
  }
}
void shuffleArray(vector<int> &array) {
  for (int i = 0; i < array.size(); ++ i) {
    swap(array[i], (rand % array.size()));
  }
}

Why? because some elements may be swapped more than once. For example:

[1, 2, 3] // lets swap 1 and 2
[2, 1, 3] // lets swap 1 and 3
[2, 3, 1]

For each solution to be fairly picked, we need to rule out the elements that have been swapped out. Considering two baskets, each time, you randomly pick some egg (number) from that basket and put it in order into another one. The numbers that are put to another could not be chosen again. This is the idea of the Fisher-Yates Random shuffle algorithm.

C++ Random Shuffle Algorithm

We can do this in-place by the following C++ implementation:

1
2
3
4
5
6
void shuffleArray(vector<int> &array) {
  for (int i = 0; i < array.size(); ++ i) {
    // random(a, b) returns a random number between a (inclusive) and b (exclusive)
    swap(array[i], random(i, array.size());
  }
}
void shuffleArray(vector<int> &array) {
  for (int i = 0; i < array.size(); ++ i) {
    // random(a, b) returns a random number between a (inclusive) and b (exclusive)
    swap(array[i], random(i, array.size());
  }
}

We get a random index between the current index i to the size of the list, thus separating the list into two parts: the basket chosen and the basket to choose from. The time complexity for Fisher-Yates Random Shuffle algorithm is O(N) and space complexity is O(1) constant where the swapping takes inplace.

Random Shuffling in Magik

With SW521, the Random object has been re-implemented using Java Interop Library (make use of the java.util.Random object), the random.between() method generates a random integer between two bounds (inclusive). The following is the Random Shuffle extended API to the Magik programming language.

_package sw
$

_pragma(classify_level=public, topic=random)
_method random.shuffle(list)
    ## Shuffle an array using Fisher–Yates
    ## 
    _local i << 1, len << list.size
    _while i <= len
    _loop
        _local j << _self.between(i, len)
        (list[i], list[j]) << (list[j], list[i]) # swapping in Pythonic way.
        i +<< 1
    _endloop
    >> list
_endmethod

Random Shuffling Algorithms

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
514 words
Last Post: How to Run a Specified Set of Javascript (NodeJS) Unit Tests using Mocha?
Next Post: Algorithms to Check if a Graph is a Valid Tree by Using Disjoint Set (Union Find) and Breadth First Search

The Permanent URL is: The Fisher–Yates Random Shuffle Algorithm

Leave a Reply