How to make the array shuffle function give different results on subsequent calls

I have the following function that works the way I want for a single call:

let shuffle (arr : 'a array) =
    let array = Array.copy arr
    let rng = new Random()
    let n = array.Length
    for x in 1..n do
        let i = n-x
        let j = rng.Next(i+1)
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp
    array

However, for multiple calls, as in the following (x is not used for anything), it gives the same shuffle for each call. How can I make a shuffle every time?

[for x in 1..3 do yield shuffle [|1;2;3|]]

>
val it : int [] list = [[|1; 3; 2|]; [|1; 3; 2|]; [|1; 3; 2|]]
+4
source share
1 answer

You want to move the random value outside the function as follows:

let rng = new Random()
let shuffle (arr : 'a array) =
    let array = Array.copy arr
    let n = array.Length
    for x in 1..n do
        let i = n-x
        let j = rng.Next(i+1)
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp
    array

The reason is that by default, RNG is sown in time, which in a closed loop does not change enough. Moving rng outside the function means that it is stored on all calls.

+5
source

All Articles