-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcombinatorics.go
144 lines (121 loc) · 4.41 KB
/
combinatorics.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package chains
import (
"iter"
)
func oneAtATime[T any](vals []T) iter.Seq2[T, []T] {
// { 1 2 3} -> {[1, {2, 3}], [2, {1, 3}], [3, {1, 3}], ...}
return func(yield func(T, []T) bool) {
for index := range len(vals) {
oneVal := vals[index]
// Need to copy slice so we don't overwrite it
tmp := make([]T, len(vals))
copy(tmp, vals)
tailVal := tmp[:index+copy(tmp[index:], tmp[index+1:])]
if !yield(oneVal, tailVal) {
return
}
}
}
}
func oneAtATimeWithReplacement[T any](vals []T) iter.Seq2[T, []T] {
// { 1 2 3} -> {[1, {1, 2, 3}], [2, {1, 2, 3}], [3, {1, 2, 3}], ...}
return func(yield func(T, []T) bool) {
for index := range len(vals) {
oneVal := vals[index]
if !yield(oneVal, vals) {
return
}
}
}
}
func oneAtATimeTail[T any](vals []T) iter.Seq2[T, []T] {
// { 1 2 3} -> {[1, {2, 3}], [2, {3}], ...}
return func(yield func(T, []T) bool) {
for index := range len(vals) {
oneVal := vals[index]
tailVal := vals[index+1:]
if !yield(oneVal, tailVal) {
return
}
}
}
}
func combinationsAndPermutations[T any](placementArray []T, vals []T, index int, length int, returnall bool, visit func([]T) iter.Seq2[T, []T], yield func([]T) bool) bool {
if index >= length {
return false
}
for item, rest := range visit(vals) {
placementArray[index] = item
if (index == length-1) || returnall {
copyToReturn := make([]T, index+1)
copy(copyToReturn, placementArray[:index+1])
if !yield(copyToReturn) {
return true
}
}
if len(rest) > 0 && index < length {
if combinationsAndPermutations(placementArray, rest, index+1, length, returnall, visit, yield) {
return true
}
}
}
return false
}
// AllPermutations will yield all permutations without replacement of
// every subset of items in the sequence of all length
// { 1 2 3 } -> {1, 2, 3} {1 3 2} {2 1 3} {2 3 1} {3 1 2} {3 2 1}
func AllPermutations[T any](vals []T) iter.Seq[[]T] {
return func(yield func([]T) bool) {
placement := make([]T, len(vals))
combinationsAndPermutations(placement, vals, 0, len(vals), true, oneAtATime, yield)
}
}
// PermutationsOfLength will yield all orderings without replacement of
// a specified length
// { 1 2 3 }, 2 -> { 1 2 } { 1 3 } { 2 1 } { 2 3 } { 3 1 } { 3 2 }
func PermutationsOfLength[T any](vals []T, length int) iter.Seq[[]T] {
return func(yield func([]T) bool) {
placement := make([]T, len(vals))
combinationsAndPermutations(placement, vals, 0, length, false, oneAtATime, yield)
}
}
// Permutations will yield all possible orderings of the slice
// { 1 2 3 } -> { 1 2 3 } { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 1 2 } { 3 2 1 }
func Permutations[T any](vals []T) iter.Seq[[]T] {
return PermutationsOfLength(vals, len(vals))
}
// PermutationsOfLengthWithReplacement will yield all combinations with replacement of
// a specified length
// { 1 2 3 }, 2 -> { 1 2 } { 1 3 } { 2 1 } { 2 3 } { 3 1 } { 3 2 }
func PermutationsOfLengthWithReplacement[T any](vals []T, length int) iter.Seq[[]T] {
return func(yield func([]T) bool) {
placement := make([]T, len(vals))
combinationsAndPermutations(placement, vals, 0, length, false, oneAtATimeWithReplacement, yield)
}
}
// PermutationsWithReplacement will yield all possible orderings of the slice with replacement
// { 1 2 3 } -> { 1 1 1 } { 1 1 2 } { 1 1 3 } { 2 1 1 } ... { 3 3 3 }
func PermutationsWithReplacement[T any](vals []T) iter.Seq[[]T] {
return PermutationsOfLengthWithReplacement(vals, len(vals))
}
// CombinationsOfLength will yield all combinations with replacement of
// a specified length
// { 1 2 3 }, 2 -> { 1 } { 1 2 } { 1 3 } { 2 } { 2 1 } { 2 3 } { 3 } { 3 1 } { 3 2 }
func CombinationsOfLength[T any](vals []T, length int) iter.Seq[[]T] {
return func(yield func([]T) bool) {
placement := make([]T, len(vals))
combinationsAndPermutations(placement, vals, 0, length, false, oneAtATimeTail, yield)
}
}
// Combinations will yield all combinations with replacement of
// the entire slice
// { 1 2 3 } -> { 1 } { 1 2 } { 1 2 3 } { 1 3 } { 1 3 2 } { 2 } { 2 1 } { 2 1 3 } { 2 3 } { 2 3 1 } { 3 } { 3 1 } { 3 1 2 } { 3 2 } { 3 2 1 }
func Combinations[T any](vals []T) iter.Seq[[]T] {
return CombinationsOfLength(vals, len(vals))
}
// Pairwise will yield all possible combinations of the two iterators
// { "a" "b" }, { 1 2 } -> iter{ ( "a" 1 ) ( "a" 2 ) ( "b" 1 ) ( "b" 2 ) }
func Pairwise[T, V any](s1 iter.Seq[T], s2 iter.Seq[V]) iter.Seq2[T, V] {
i1, i2 := Tee(s1)
return Zip(Cycle(i1), Lengthen(s2, Count(i2)))
}