-
Notifications
You must be signed in to change notification settings - Fork 1
/
searching.go
151 lines (119 loc) · 2.72 KB
/
searching.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
145
146
147
148
149
150
151
package ranges
// All returns true if `cb` returns `true` for all elements
func All[T any](r InputRange[T], cb func(element T) bool) bool {
for !r.Empty() {
if !cb(r.Front()) {
return false
}
r.PopFront()
}
return true
}
// AllS is `All` accepting a slice.
func AllS[T any](r []T, cb func(element T) bool) bool {
return All[T](SliceRange(r), cb)
}
// Any returns true if `cb` returns `true` for any element
func Any[T any](r InputRange[T], cb func(element T) bool) bool {
for !r.Empty() {
if cb(r.Front()) {
return true
}
r.PopFront()
}
return false
}
// AnyS is `Any` accepting a slice.
func AnyS[T any](r []T, cb func(element T) bool) bool {
return Any[T](SliceRange(r), cb)
}
// Among returns `true` is `value` is equal to any of the `values` according to `eq`
func Among[T any](eq func(a, b T) bool, value T, values ...T) bool {
for _, b := range values {
if eq(value, b) {
return true
}
}
return false
}
// AmongEq implements `Among` with `==` for any comparable type.
func AmongEq[T comparable](value T, values ...T) bool {
for _, b := range values {
if value == b {
return true
}
}
return false
}
// StartsWith returns `true` if `r1` starts with `r2` according to `cb`
func StartsWith[T any, U any](
r1 InputRange[T],
r2 InputRange[U],
cb func(element1 T, element2 U) bool,
) bool {
for !r1.Empty() && !r2.Empty() {
if !cb(r1.Front(), r2.Front()) {
return false
}
r1.PopFront()
r2.PopFront()
}
return r2.Empty()
}
// SkipOver sets `haystack` to the range after `needle`, if and only if
// `haystack` starts with `needle`.
func SkipOver[T any, U any](
haystack *ForwardRange[T],
needle InputRange[U],
cb func(element1 T, element2 U) bool,
) bool {
if haystack == nil || (*haystack).Empty() {
return true
}
skipped := (*haystack).Save()
for !skipped.Empty() && !needle.Empty() {
if !cb(skipped.Front(), needle.Front()) {
return false
}
skipped.PopFront()
needle.PopFront()
}
*haystack = skipped
return true
}
// Length returns the length of a range in O(n) time.
//
// The range is exhausted.
//
// If your range is a RandomAccessRange, use `r.Len()` instead.
func Length[T any](r InputRange[T]) int {
count := 0
for !r.Empty() {
count++
r.PopFront()
}
return count
}
// Count returns the number of elements where `cb` returns `true`
func Count[T any](r InputRange[T], cb func(element T) bool) int {
count := 0
for !r.Empty() {
if cb(r.Front()) {
count++
}
r.PopFront()
}
return count
}
// CountUntil returns the number of elements until `cb` returns `true`
func CountUntil[T any](r InputRange[T], cb func(element T) bool) int {
count := 0
for !r.Empty() {
if cb(r.Front()) {
return count
}
count++
r.PopFront()
}
return count
}