github.com/chaowen112/go-lib@v0.0.0-20231018124935-124cd26d7cbe/randutils/shuffle.go (about)

     1  package randutils
     2  
     3  // Shuffle pseudo-randomizes the order of elements.
     4  // n is the number of elements. Shuffle panics if n < 0.
     5  // swap swaps the elements with indexes i and j.
     6  func Shuffle(n int, swap func(i, j int)) {
     7  	if n < 0 {
     8  		panic("invalid argument to Shuffle")
     9  	}
    10  
    11  	// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
    12  	// Shuffle really ought not be called with n that doesn't fit in 32 bits.
    13  	// Not only will it take a very long time, but with 2³¹! possible permutations,
    14  	// there's no way that any PRNG can have a big enough internal state to
    15  	// generate even a minuscule percentage of the possible permutations.
    16  	// Nevertheless, the right API signature accepts an int n, so handle it as best we can.
    17  	i := n - 1
    18  	for ; i > 1<<31-1-1; i-- {
    19  		j := int(Uint32n(uint32(i + 1)))
    20  		swap(i, j)
    21  	}
    22  	for ; i > 0; i-- {
    23  		j := int(Uint32n(uint32(i + 1)))
    24  		swap(i, j)
    25  	}
    26  }