You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.0 KiB
99 lines
2.0 KiB
package collect |
|
|
|
// CartesianCount 笛卡尔积组合数 |
|
func CartesianCount[T any](sets ...[]T) (total int) { |
|
total = 1 |
|
for _, set := range sets { |
|
total *= len(set) |
|
} |
|
return |
|
} |
|
|
|
// CartesianProduct 笛卡尔积(返回所有可能的组合) |
|
// 输入: [][]T 类型的二维切片 |
|
// 输出: []T 类型的切片组成的切片 |
|
func CartesianProduct[T any](sets ...[]T) [][]T { |
|
if len(sets) == 0 { |
|
return [][]T{{}} |
|
} |
|
|
|
// 初始化为第一个集合的所有单元素组合 |
|
result := make([][]T, len(sets[0])) |
|
for i, v := range sets[0] { |
|
result[i] = []T{v} |
|
} |
|
|
|
// 依次处理后续每一组 |
|
for _, set := range sets[1:] { |
|
if len(set) == 0 { |
|
return [][]T{} |
|
} |
|
|
|
newResult := make([][]T, 0, len(result)*len(set)) |
|
|
|
for _, prev := range result { |
|
for _, curr := range set { |
|
// 预分配空间,避免频繁扩容 |
|
combined := make([]T, 0, len(prev)+1) |
|
combined = append(combined, prev...) |
|
combined = append(combined, curr) |
|
newResult = append(newResult, combined) |
|
} |
|
} |
|
|
|
result = newResult |
|
} |
|
|
|
return result |
|
} |
|
|
|
// CartesianYield 生成笛卡尔积的所有组合,并为每个组合调用回调函数 |
|
// callback: func(comb []T) bool - 处理当前组合,返回 true 继续生成,返回 false 停止 |
|
// return: 生成的组合总数 |
|
func CartesianYield[T any](sets [][]T, callback func([]T) bool) int { |
|
if len(sets) == 0 { |
|
return 0 |
|
} |
|
|
|
// 检查是否有空集 |
|
for _, s := range sets { |
|
if len(s) == 0 { |
|
return 0 |
|
} |
|
} |
|
|
|
// 初始化索引计数器 |
|
indices := make([]int, len(sets)) |
|
comb := make([]T, len(sets)) // 复用缓冲区,避免每次分配 |
|
|
|
count := 0 |
|
for { |
|
// 构建当前组合 |
|
for i, idx := range indices { |
|
comb[i] = sets[i][idx] |
|
} |
|
|
|
// 调用回调 |
|
count++ |
|
if !callback(comb) { |
|
break // 停止生成 |
|
} |
|
|
|
// 递增索引,像计数器一样 |
|
i := len(indices) - 1 |
|
for i >= 0 { |
|
indices[i]++ |
|
if indices[i] < len(sets[i]) { |
|
break |
|
} |
|
indices[i] = 0 |
|
i-- |
|
} |
|
|
|
if i < 0 { |
|
break // 所有组合已生成 |
|
} |
|
} |
|
|
|
return count |
|
}
|
|
|