Skip to content

Latest commit

 

History

History
136 lines (100 loc) · 3.54 KB

README_English.md

File metadata and controls

136 lines (100 loc) · 3.54 KB

English Document

中文文档

Shuffle Algorithm

1. the support of the shuffle algorithm

Definition of a shuffling algorithm: An algorithm that generates random sorting for a list.

Currently supported shuffle algorithm:

  • Fisher–Yates-Knuth
  • Scatology

2. Installation

go get -u github.com/golang-infrastructure/go-shuffle

3. API code examples

3.1 Slicing shuffle

package main

import (
	"fmt"
	"github.com/golang-infrastructure/go-shuffle"
)

func main() {

	// 对切片中的元素shuffle
	slice := []int{1, 2, 3, 4, 5}
	shuffle.Shuffle(slice)
	fmt.Println(slice)
	// Output:
	// [5 1 2 3 4]

}

3.2 Matrix shuffle

package main

import (
	"fmt"
	"github.com/golang-infrastructure/go-shuffle"
)

func main() {

	// shuffle the elements of a two-dimensional matrix
	matrix := [][]int{
		{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
		{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
		{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
		{31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
	}
	// Note that errors may be returned, such as a two-dimensional array that cannot be shuffled if each row has different lengths
	err := shuffle.ShuffleMatrix(matrix)
	if err != nil {
		fmt.Println("Shuffle matrix failed: " + err.Error())
		return
	}
	fmt.Println(matrix)
	// Output:
	// [[11 40 6 23 15 28 4 7 37 21] [29 26 33 5 35 13 22 32 19 34] [31 30 36 20 2 10 24 39 9 27] [16 8 18 14 1 17 38 12 25 3]]

}

4. Fisher–Yates-Knuth Shuffling algorithm

Suppose you now have an array:

[1, 2, 3, 4, 5]

Starting from the rightmost coordinate 'len(slice)-1' as' right_index ', randomly select a subscript from '[0, right_index]' each time, swap the value of the selected subscript with 'right_index', and subtract 'right_index' one offset to the left.

Examples of code:

// Use its own independent random number generator to distinguish it from other calls
var standaloneRand = rand.New(rand.NewSource(time.Now().Unix()))

// FisherYatesKnuthShuffle Fisher–Yates-Knuth Shuffle或 算法对一维数组洗牌,O(n)
func FisherYatesKnuthShuffle[T any](slice []T) {
	for index := len(slice) - 1; index > 0; index-- {
		chooseIndex := standaloneRand.Intn(index + 1)
		slice[chooseIndex], slice[index] = slice[index], slice[chooseIndex]
	}
}

By extending the above algorithm, we can easily obtain the shuffle algorithm of the matrix. Each row of the matrix is regarded as a concatenated one-dimensional array, and the shuffle algorithm of the matrix is converted into the shufle algorithm of slices. Shufle of slices has already been implemented:

// FisherYatesShuffleMatrix Fisher–Yates-Knuth The shuffle algorithm shuffles the matrix
func FisherYatesShuffleMatrix[T any](matrix [][]T) error {

	// Parameter check
	if err := check(matrix); err != nil {
		return err
	}

	row, col := len(matrix), len(matrix[0])
	for index := row*col - 1; index > 0; index-- {
		chooseIndex := standaloneRand.Intn(index + 1)
		matrix[index/col][index%col], matrix[chooseIndex/col][chooseIndex%col] = matrix[chooseIndex/col][chooseIndex%col], matrix[index/col][index%col]
	}

	return nil
}

// You need to ensure that the incoming two-dimensional data is a matrix, otherwise you may cross the panic line later
func check[T any](matrix [][]T) error {
	for i := 1; i < len(matrix); i++ {
		if len(matrix[i]) != len(matrix[i-1]) {
			return ErrMatrixUnavailable
		}
	}
	return nil
}

5. Scatology algorithm

That is, the rightmost '[0,right_index]' is no longer selected at random based on Fisher-Yates -Knuth, and the details are no longer expanded.