summaryrefslogtreecommitdiffstats
path: root/aoc23/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'aoc23/util.go')
-rw-r--r--aoc23/util.go182
1 files changed, 100 insertions, 82 deletions
diff --git a/aoc23/util.go b/aoc23/util.go
index 097f413..269a98a 100644
--- a/aoc23/util.go
+++ b/aoc23/util.go
@@ -11,46 +11,6 @@ import (
"testing"
)
-type Set[V comparable] struct{ set map[V]bool }
-
-func (s *Set[V]) Add(v V) bool {
- _, ok := s.set[v]
- if !ok {
- if s.set == nil {
- s.set = make(map[V]bool)
- }
- s.set[v] = true
- }
- return !ok
-}
-
-func (s *Set[V]) AddAll(vs []V) bool {
- changed := false
- for _, v := range vs {
- if s.Add(v) {
- changed = true
- }
- }
- return changed
-}
-
-func (s *Set[V]) Contains(v V) bool {
- _, ok := s.set[v]
- return ok
-}
-
-func (s *Set[V]) Slice() []V {
- values := make([]V, 0, len(s.set))
- for v := range s.set {
- values = append(values, v)
- }
- return values
-}
-
-func (s *Set[V]) Len() int { return len(s.set) }
-
-func (s *Set[V]) Reset() { clear(s.set) }
-
func assert(t *testing.T, want, got int) {
t.Helper()
if got != want {
@@ -65,13 +25,17 @@ func run(f func(r io.Reader) int, r io.Reader) int {
return f(r)
}
-func partial[V1, V2, R any](f func(V1, V2) R, frozenArg V2) func(V1) R {
- return func(v1 V1) R { return f(v1, frozenArg) }
+func inputFile(day int) *os.File {
+ f, err := os.Open(fmt.Sprintf("input/input%02d.txt", day))
+ if err != nil {
+ panic(err)
+ }
+ return f
}
-func compose[V1, R1, R2 any](f1 func(V1) R1, f2 func(R1) R2) func(V1) R2 {
- return func(v V1) R2 { return f2(f1(v)) }
-}
+func inputString(s string) io.Reader { return strings.NewReader(strings.TrimSpace(s)) }
+
+// Parsing
func parseLines[T any](r io.Reader, parser func(line string) T) []T {
scanner := bufio.NewScanner(r)
@@ -80,19 +44,12 @@ func parseLines[T any](r io.Reader, parser func(line string) T) []T {
line := strings.TrimSpace(scanner.Text())
values = append(values, parser(line))
}
- return values
-}
-
-func inputFile(day int) *os.File {
- f, err := os.Open(fmt.Sprintf("input/input%02d.txt", day))
- if err != nil {
+ if err := scanner.Err(); err != nil {
panic(err)
}
- return f
+ return values
}
-func inputString(s string) io.Reader { return strings.NewReader(strings.TrimSpace(s)) }
-
func requireInt(s string) int {
n, err := strconv.Atoi(s)
if err != nil {
@@ -105,25 +62,15 @@ func runes(s string) []rune { return []rune(s) }
func isDigit(r rune) bool { return int(r) >= 48 && int(r) <= 57 }
-func max(a, b int) int {
- if a > b {
- return a
- }
- return b
-}
+// Functional
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
+func partial[V1, V2, R any](f func(V1, V2) R, frozenArg V2) func(V1) R {
+ return func(v1 V1) R { return f(v1, frozenArg) }
}
-func add(a, b int) int { return a + b }
-
-func mul(a, b int) int { return a * b }
-
-func pow(a, b int) int { return int(math.Pow(float64(a), float64(b))) }
+func compose[V1, R1, R2 any](f1 func(V1) R1, f2 func(R1) R2) func(V1) R2 {
+ return func(v V1) R2 { return f2(f1(v)) }
+}
func reduce[V any](values []V, f func(a, b V) V, initial V) V {
acc := initial
@@ -133,25 +80,26 @@ func reduce[V any](values []V, f func(a, b V) V, initial V) V {
return acc
}
-func map2[V any, R any](values []V, f func(v V) R) []R {
- mapped := make([]R, len(values))
+// map is reserved :(
+func transform[V any, R any](values []V, f func(v V) R) []R {
+ result := make([]R, len(values))
for i, v := range values {
- mapped[i] = f(v)
+ result[i] = f(v)
}
- return mapped
+ return result
}
func filter[V any](values []V, pred func(v V) bool) []V {
- var filtered []V
+ var result []V
for _, v := range values {
if pred(v) {
- filtered = append(filtered, v)
+ result = append(result, v)
}
}
- return filtered
+ return result
}
-func frequency[V any](values []V, pred func(v V) bool) int {
+func quantify[V any](values []V, pred func(v V) bool) int {
n := 0
for _, v := range values {
if pred(v) {
@@ -161,14 +109,84 @@ func frequency[V any](values []V, pred func(v V) bool) int {
return n
}
-func anyMatch[V any](values []V, pred func(v V) bool) bool { return frequency(values, pred) > 0 }
+func some[V any](values []V, pred func(v V) bool) bool { return quantify(values, pred) > 0 }
-func allMatch[V any](values []V, pred func(v V) bool) bool {
- return frequency(values, pred) == len(values)
+func all[V any](values []V, pred func(v V) bool) bool {
+ return quantify(values, pred) == len(values)
}
-func noneMatch[V any](values []V, pred func(v V) bool) bool { return !anyMatch(values, pred) }
+func none[V any](values []V, pred func(v V) bool) bool { return quantify(values, pred) == 0 }
+
+// Math
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func add(a, b int) int { return a + b }
+
+func mul(a, b int) int { return a * b }
+
+func pow(a, b int) int { return int(math.Pow(float64(a), float64(b))) }
func product(ints []int) int { return reduce(ints, mul, 1) }
func sum(ints []int) int { return reduce(ints, add, 0) }
+
+// Collections
+
+type Set[V comparable] struct{ set map[V]bool }
+
+func NewSet[V comparable](vs []V) *Set[V] {
+ set := Set[V]{}
+ set.AddAll(vs)
+ return &set
+}
+
+func (s *Set[V]) Add(v V) bool {
+ _, ok := s.set[v]
+ if !ok {
+ if s.set == nil {
+ s.set = make(map[V]bool)
+ }
+ s.set[v] = true
+ }
+ return !ok
+}
+
+func (s *Set[V]) AddAll(vs []V) bool {
+ changed := false
+ for _, v := range vs {
+ if s.Add(v) {
+ changed = true
+ }
+ }
+ return changed
+}
+
+func (s *Set[V]) Contains(v V) bool {
+ _, ok := s.set[v]
+ return ok
+}
+
+func (s *Set[V]) Slice() []V {
+ values := make([]V, 0, len(s.set))
+ for v := range s.set {
+ values = append(values, v)
+ }
+ return values
+}
+
+func (s *Set[V]) Len() int { return len(s.set) }
+
+func (s *Set[V]) Reset() { clear(s.set) }