4

I have the following function which works how 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 (the x isn't used for anything), it yields the same shuffle for each call. How do I make it yield a different shuffle each 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|]]
rytido
  • 472
  • 3
  • 15

1 Answers1

5

You want to move the random outside the function like so:

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 the RNG is seeded by the time by default, which in a tight loop doesn't change enough. Moving the rng outside the function means that it persists across calls.

John Palmer
  • 25,356
  • 3
  • 48
  • 67