-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathproduct.go
52 lines (41 loc) · 1.26 KB
/
product.go
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
41
42
43
44
45
46
47
48
49
50
51
52
package iterium
import (
"math"
)
// ProductCount calculates the number of Cartesian products with repeat.
func ProductCount(countOfSymbols, repeat int) int64 {
return int64(math.Pow(float64(countOfSymbols), float64(repeat)))
}
// Product generates a Cartesian product for a given slice of elements with a repeat.
func Product[T any](symbols []T, repeat int) Iter[[]T] {
total := ProductCount(len(symbols), repeat)
// Create a new channel receiving slices.
iter := Instance[[]T](total, false)
start, end := 0, len(symbols)-1
slice := make([]int, repeat)
// Create a slice of length `repeat` and initialize it with the value `start`
for i := 0; i < repeat; i++ {
slice[i] = start
}
go func() {
defer IterRecover()
defer iter.Close()
// Generate all possible combinations of `repeat` elements
// from the integer slice `[start, end]`.
for step := uint(0); step < uint(total); step++ {
result := make([]T, repeat)
replacePlaceholders[T](symbols, slice, &result)
iter.Chan() <- result
// Increment the rightmost element of the combination by 1
// and propagate the carry to the left if necessary.
for i := repeat - 1; i >= 0; i-- {
slice[i]++
if slice[i] <= end {
break
}
slice[i] = start
}
}
}()
return iter
}