题目一:公司有n个组,>=5,每组人数相同,>=2人,需要进行随机的组队吃饭。
要求:
-
两两一队或三人一队,不能落单
-
两人队、三人队各自的队伍数均不得少于2
-
一个人只出现一次
-
队伍中所有人不能来自相同组
-
随机组队,重复执行程序得到的结果不一样,总队伍数也不能一样
-
注释注释注释
注:要同时满足条件1-6,
举例:
GroupList = [ # 小组列表
['小名', '小红', '小马', '小丽', '小强'],
['大壮', '大力', '大1', '大2', '大3'],
['阿花', '阿朵', '阿蓝', '阿紫', '阿红'],
['A', 'B', 'C', 'D', 'E'],
['一', '二', '三', '四', '五'],
['建国', '建军', '建民', '建超', '建跃'],
['爱民', '爱军', '爱国', '爱辉', '爱月']
]
输入:GroupList
示例输出: [小强 大3] [阿红 E] [五 建跃] [爱月 小名] [大壮 阿花] [A 一] [建国 爱民] [小红 大力] [阿朵 B] [二 建军] [爱军 小马] [大1 阿蓝] [C 三] [建民 爱国 小丽] [大2 阿紫 D] [四 建超 爱辉]
package main
import (
"fmt"
"math/rand"
)
type Variables struct {
x int
y int
}
// 根据数学推导,算出 x*2+3*y=size 所有解的方案
func calSet(size int) Variables {
result := make([]Variables, 0)
// 1. 两两一队或三人一队,不能落单
// 2. 两人队、三人队各自的队伍数均不得少于2
for x := 2; x < size-3*2; x++ {
num := size - 2*x // 减去两人队剩余人数
if num%3 == 0 && num/3 >= 2 {
result = append(result, Variables{x, (size - 2*x) / 3})
}
}
// 没有符合题意的组队方式
if len(result) == 0 {
return Variables{}
}
return result[rand.Int()%len(result)] // 5. 随机组队,重复执行程序得到的结果不一样,总队伍数也不能一样
}
func main() {
var groupList = [][]string{ // 小组列表
{"小名", "小红", "小马", "小丽", "小强"},
{"大壮", "大力", "大1", "大2", "大3"},
{"阿花", "阿朵", "阿蓝", "阿紫", "阿红"},
{"A", "B", "C", "D", "E"},
{"一", "二", "三", "四", "五"},
{"建国", "建军", "建民", "建超", "建跃"},
{"爱民", "爱军", "爱国", "爱辉", "爱月"},
}
size := len(groupList) * len(groupList[0])
cs := calSet(size) // 计算总人数,得到一组随机组合
fmt.Println("随机返回的序列", cs)
if cs.x == 0 {
fmt.Println("没有符合题意的组合")
return
}
index := 0
column := len(groupList)
data := make([][]string, cs.x+cs.y)
for i := 0; i < size; i++ {
data[index] = append(data[index], groupList[i%column][i/column])
if i < cs.x*2 && len(data[index]) == 2 { // 先排两人队
index++
} else if i > cs.x*2 && len(data[index]) == 3 { // 再排三人队
index++
}
}
fmt.Println(data)
// 优化:可以把 groupList 的每一组随意打乱,
// 这样就可以避免按照二维数组左上角,从上到下,从左到右 固定取数据的影响
}