| 
 | 1 | +[English Document](./README_English.md)  | 
 | 2 | + | 
 | 3 | +[中文文档](./README.md)  | 
 | 4 | + | 
 | 5 | +# Shuffle Algorithm  | 
 | 6 | + | 
 | 7 | +# 1. the support of the shuffle algorithm  | 
 | 8 | + | 
 | 9 | +Definition of a shuffling algorithm: An algorithm that generates random sorting for a list.  | 
 | 10 | + | 
 | 11 | +Currently supported shuffle algorithm:  | 
 | 12 | + | 
 | 13 | +- Fisher–Yates-Knuth  | 
 | 14 | +- Scatology  | 
 | 15 | + | 
 | 16 | +# 2. Installation  | 
 | 17 | + | 
 | 18 | +```bash  | 
 | 19 | +go get -u github.com/golang-infrastructure/go-shuffle  | 
 | 20 | +```  | 
 | 21 | + | 
 | 22 | +# 3. API code examples  | 
 | 23 | + | 
 | 24 | +## 3.1 Slicing shuffle  | 
 | 25 | + | 
 | 26 | +```go  | 
 | 27 | +package main  | 
 | 28 | + | 
 | 29 | +import (  | 
 | 30 | +	"fmt"  | 
 | 31 | +	"github.com/golang-infrastructure/go-shuffle"  | 
 | 32 | +)  | 
 | 33 | + | 
 | 34 | +func main() {  | 
 | 35 | + | 
 | 36 | +	// 对切片中的元素shuffle  | 
 | 37 | +	slice := []int{1, 2, 3, 4, 5}  | 
 | 38 | +	shuffle.Shuffle(slice)  | 
 | 39 | +	fmt.Println(slice)  | 
 | 40 | +	// Output:  | 
 | 41 | +	// [5 1 2 3 4]  | 
 | 42 | + | 
 | 43 | +}  | 
 | 44 | +```  | 
 | 45 | + | 
 | 46 | +## 3.2 Matrix shuffle  | 
 | 47 | + | 
 | 48 | +```go  | 
 | 49 | +package main  | 
 | 50 | + | 
 | 51 | +import (  | 
 | 52 | +	"fmt"  | 
 | 53 | +	"github.com/golang-infrastructure/go-shuffle"  | 
 | 54 | +)  | 
 | 55 | + | 
 | 56 | +func main() {  | 
 | 57 | + | 
 | 58 | +	// shuffle the elements of a two-dimensional matrix  | 
 | 59 | +	matrix := [][]int{  | 
 | 60 | +		{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},  | 
 | 61 | +		{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},  | 
 | 62 | +		{21, 22, 23, 24, 25, 26, 27, 28, 29, 30},  | 
 | 63 | +		{31, 32, 33, 34, 35, 36, 37, 38, 39, 40},  | 
 | 64 | +	}  | 
 | 65 | +	// Note that errors may be returned, such as a two-dimensional array that cannot be shuffled if each row has different lengths  | 
 | 66 | +	err := shuffle.ShuffleMatrix(matrix)  | 
 | 67 | +	if err != nil {  | 
 | 68 | +		fmt.Println("Shuffle matrix failed: " + err.Error())  | 
 | 69 | +		return  | 
 | 70 | +	}  | 
 | 71 | +	fmt.Println(matrix)  | 
 | 72 | +	// Output:  | 
 | 73 | +	// [[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]]  | 
 | 74 | + | 
 | 75 | +}  | 
 | 76 | +```  | 
 | 77 | + | 
 | 78 | +# 4. Fisher–Yates-Knuth Shuffling algorithm  | 
 | 79 | + | 
 | 80 | +Suppose you now have an array:  | 
 | 81 | + | 
 | 82 | +```  | 
 | 83 | +[1, 2, 3, 4, 5]  | 
 | 84 | +```  | 
 | 85 | + | 
 | 86 | +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.  | 
 | 87 | + | 
 | 88 | +Examples of code:  | 
 | 89 | + | 
 | 90 | +```go  | 
 | 91 | +// Use its own independent random number generator to distinguish it from other calls  | 
 | 92 | +var standaloneRand = rand.New(rand.NewSource(time.Now().Unix()))  | 
 | 93 | + | 
 | 94 | +// FisherYatesKnuthShuffle Fisher–Yates-Knuth Shuffle或 算法对一维数组洗牌,O(n)  | 
 | 95 | +func FisherYatesKnuthShuffle[T any](slice []T) {  | 
 | 96 | +	for index := len(slice) - 1; index > 0; index-- {  | 
 | 97 | +		chooseIndex := standaloneRand.Intn(index + 1)  | 
 | 98 | +		slice[chooseIndex], slice[index] = slice[index], slice[chooseIndex]  | 
 | 99 | +	}  | 
 | 100 | +}  | 
 | 101 | +```  | 
 | 102 | + | 
 | 103 | +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:  | 
 | 104 | + | 
 | 105 | +```go  | 
 | 106 | +// FisherYatesShuffleMatrix Fisher–Yates-Knuth The shuffle algorithm shuffles the matrix  | 
 | 107 | +func FisherYatesShuffleMatrix[T any](matrix [][]T) error {  | 
 | 108 | + | 
 | 109 | +	// Parameter check  | 
 | 110 | +	if err := check(matrix); err != nil {  | 
 | 111 | +		return err  | 
 | 112 | +	}  | 
 | 113 | + | 
 | 114 | +	row, col := len(matrix), len(matrix[0])  | 
 | 115 | +	for index := row*col - 1; index > 0; index-- {  | 
 | 116 | +		chooseIndex := standaloneRand.Intn(index + 1)  | 
 | 117 | +		matrix[index/col][index%col], matrix[chooseIndex/col][chooseIndex%col] = matrix[chooseIndex/col][chooseIndex%col], matrix[index/col][index%col]  | 
 | 118 | +	}  | 
 | 119 | + | 
 | 120 | +	return nil  | 
 | 121 | +}  | 
 | 122 | + | 
 | 123 | +// You need to ensure that the incoming two-dimensional data is a matrix, otherwise you may cross the panic line later  | 
 | 124 | +func check[T any](matrix [][]T) error {  | 
 | 125 | +	for i := 1; i < len(matrix); i++ {  | 
 | 126 | +		if len(matrix[i]) != len(matrix[i-1]) {  | 
 | 127 | +			return ErrMatrixUnavailable  | 
 | 128 | +		}  | 
 | 129 | +	}  | 
 | 130 | +	return nil  | 
 | 131 | +}  | 
 | 132 | +```  | 
 | 133 | + | 
 | 134 | +# 5. Scatology algorithm  | 
 | 135 | + | 
 | 136 | +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.  | 
0 commit comments