Search code examples
arraysgorandomshuffleentropy

Algorithm to randomize output order of a short array in Go


The key difference between this question and the lots of duplicated answers is that, the input array is short, only 3 elements. --

Say I have an ordered set of int. The size of array is only 3 (or a bit more). I need to randomize their order and return a new array. Although it is a pure algorithm question, but the prefered answer language is in Go.

However, this is my code:

https://go.dev/play/p/CVu8_Q96-9F

func randShuffle(a []int) {
    rand.Seed(time.Now().UnixNano())
    rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
}

And this is one of my test run result:

[2 1 3]
[1 3 2]
[2 1 3]
[2 1 3]
[1 3 2]
[1 2 3]
[2 3 1]

which doesn't seems to be very randomized.

Any good idea to have a better randomization for a short 3-elements array?

BTW,


Solution

  • Move random.Seed from your shuffle function to the main. Seeding of a PRNG should only be done once per program, the successful mimicry of randomness is done by the state transitions of the generator rather than by the seed. Don't re-seed unless you really understand how PRNGs work and are trying to explicitly control the process for reasons such as reproducibility.

    The following straightforward modification of your code should meet your needs:

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        rand.Seed(time.Now().UnixNano())
    
        a := []int{1, 2, 3}
        for i := 0; i < 10; i++ {
            randShuffle(a)
            fmt.Println(a)
        }
    }
    
    func randShuffle(a []int) {
        rand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
    }
    

    This produces results such as:

    [2 3 1]
    [3 1 2]
    [2 1 3]
    [2 3 1]
    [1 2 3]
    [1 3 2]
    [1 2 3]
    [3 1 2]
    [3 2 1]
    [2 3 1]