diff options
Diffstat (limited to 'aoc23/util.go')
-rw-r--r-- | aoc23/util.go | 182 |
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) } |