This article describes the arrangement and combination problem of Go language implementation. Share it for your reference, as follows:
(I) Combination problem
Combination is a basic mathematical problem. The goal of this program is to output all combinations taken from m of n elements.
For example, take out 2 numbers from [1,2,3], and there are 3 combinations in total: [1,2], [1,3], [2,3]. (The combination does not consider the order, that is, [1,2] and [2,1] belong to the same combination)
The idea of this program (from other masters on the Internet):
(1) Create an array of n elements. The value of the array element is 1, which means it is selected. If it is 0, it is not selected.
(2) Initialize, set the first m elements of the array by 1, indicating that the first combination is the number of first m.
(3) Scan the "10" combination of the array element value from left to right, find the first "10" combination and turn it into "01" combination, and move all "1" on its left to the left to the leftmost end of the array.
(4) When the "10" combination is not found in a certain loop, it means that the last combination has been obtained and the loop ends.
For example, find the combination of 3 of 5:
1 1 1 0 0 //1,2,3
1 1 0 1 0 //1,2,4
1 0 1 1 0 //1,3,4
0 1 1 1 0 //2,3,4
1 1 0 0 1 //1,2,5
1 0 1 0 1 //1,3,5
0 1 1 0 1 //2,3,5
1 0 0 1 1 //1,4,5
0 1 0 1 1 //2,4,5
0 0 1 1 1 //3,4,5
Efficiency situation: Take 5 out of 20 elements, a total of 15,504 results, which takes about 10ms.
Code implementation:
import (
"fmt"
"time"
)
/*
[Arrangement and combination problem: Take m of n numbers]
*/
func Test10Base() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
m := 5
timeStart := ()
n := len(nums)
indexs := zuheResult(n, m)
result := findNumsByIndexs(nums, indexs)
timeEnd := ()
("count:", len(result))
("result:", result)
("time consume:", (timeStart))
//Is the result correct
rightCount := mathZuhe(n, m)
if rightCount == len(result) {
("Result is correct")
} else {
("The result is wrong, the correct result is:", rightCount)
}
}
//Combination algorithm (take out m numbers from nums)
func zuheResult(n int, m int) [][]int {
if m < 1 || m > n {
("Illegal argument. Param m must between 1 and len(nums).")
return [][]int{}
}
//Save the array of final results, and the total number is calculated directly through mathematical formulas
result := make([][]int, 0, mathZuhe(n, m))
//Save the array of indexes for each combination, 1 means selected, 0 means unselected
indexs := make([]int, n)
for i := 0; i < n; i++ {
if i < m {
indexs[i] = 1
} else {
indexs[i] = 0
}
}
//The first result
result = addTo(result, indexs)
for {
find := false
//Each cycle changes the first occurrence of 1 0 to 0 1, and move the left 1 to the leftmost
for i := 0; i < n-1; i++ {
if indexs[i] == 1 && indexs[i+1] == 0 {
find = true
indexs[i], indexs[i+1] = 0, 1
if i > 1 {
moveOneToLeft(indexs[:i])
}
result = addTo(result, indexs)
break
}
}
//There is no 1 0 found in this loop, which means that the last situation has been obtained
if !find {
break
}
}
return result
}
//Copy ele and add it to arr and return a new array
func addTo(arr [][]int, ele []int) [][]int {
newEle := make([]int, len(ele))
copy(newEle, ele)
arr = append(arr, newEle)
return arr
}
func moveOneToLeft(leftNums []int) {
//How many 1s are calculated
sum := 0
for i := 0; i < len(leftNums); i++ {
if leftNums[i] == 1 {
sum++
}
}
//Change the first sum to 1, and then change the next sum to 0
for i := 0; i < len(leftNums); i++ {
if i < sum {
leftNums[i] = 1
} else {
leftNums[i] = 0
}
}
}
//Get an array of elements based on the index number array
func findNumsByIndexs(nums []int, indexs [][]int) [][]int {
if len(indexs) == 0 {
return [][]int{}
}
result := make([][]int, len(indexs))
for i, v := range indexs {
line := make([]int, 0)
for j, v2 := range v {
if v2 == 1 {
line = append(line, nums[j])
}
}
result[i] = line
}
return result
}
Note: How many methods are there for taking m from n elements can be directly calculated through mathematical formulas, that is:
func mathPailie(n int, m int) int {
return jieCheng(n) / jieCheng(n-m)
}
//Mathematical method calculates the combined number (take m numbers from n)
func mathZuhe(n int, m int) int {
return jieCheng(n) / (jieCheng(n-m) * jieCheng(m))
}
//factorial
func jieCheng(n int) int {
result := 1
for i := 2; i <= n; i++ {
result *= i
}
return result
}
This formula can be used to simply verify whether the results of the above program are correct.
(II) Arrangement issues
Take out m from n numbers and arrange them. In fact, after the combination algorithm, the selected m numbers are arranged completely. The issue of full arrangement has been discussed in previous articles.
Code implementation:
//Combination results
zuhe := zuheResult(nums, m)
//Save the final arrangement result
result := make([][]int, 0)
//Transfer the combination results and arrange each item in full
for _, v := range zuhe {
p := quanPailie(v)
result = append(result, p...)
}
return result
}
//N numbers are arranged
//If you enter [1 2 3], return [123 132 213 231 312 321]
func quanPailie(nums []int) [][]int {
COUNT := len(nums)
//examine
if COUNT == 0 || COUNT > 10 {
panic("Illegal argument. nums size must between 1 and 9.")
}
//If there is only one number, return directly
if COUNT == 1 {
return [][]int{nums}
}
// Otherwise, insert the last number into all positions in the previous arrangement number
return insertItem(quanPailie(nums[:COUNT-1]), nums[COUNT-1])
}
func insertItem(res [][]int, insertNum int) [][]int {
//Save the slice of the result
result := make([][]int, len(res)*(len(res[0])+1))
index := 0
for _, v := range res {
for i := 0; i < len(v); i++ {
//Insert new element in front of each element of v
result[index] = insertToSlice(v, i, insertNum)
index++
}
//Insert new element at the end of v
result[index] = append(v, insertNum)
index++
}
return result
}
//Insert the element value into the position in the array nums index
func insertToSlice(nums []int, index int, value int) []int {
result := make([]int, len(nums)+1)
copy(result[:index], nums[:index])
result[index] = value
copy(result[index+1:], nums[index:])
return result
}
I hope this article will be helpful to everyone's Go language programming.