From e75a49801897e661f53c1143f26c9e34fbd69125 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Wed, 3 Dec 2025 20:47:27 -0600 Subject: [PATCH] refactor: clean up solution to part 1 on day 2 --- cmd/02/main.go | 41 +++--------------------- cmd/02/rnge/rnge.go | 67 ++++++++++++++++++++++++++++++++++++++++ cmd/02/rnge/rnge_test.go | 57 ++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 37 deletions(-) create mode 100644 cmd/02/rnge/rnge.go create mode 100644 cmd/02/rnge/rnge_test.go diff --git a/cmd/02/main.go b/cmd/02/main.go index d361ed8..5c33839 100644 --- a/cmd/02/main.go +++ b/cmd/02/main.go @@ -1,57 +1,24 @@ package main import ( - "strconv" "strings" + "github.com/StevanFreeborn/advent-of-code-2025/cmd/02/rnge" "github.com/StevanFreeborn/advent-of-code-2025/internal/file" ) const SeparatorCharacter = "," -const RangeSeparatorCharacter = "-" - -type Range struct { - Start int64 - End int64 -} func SolvePartOne(filePath string) int64 { input := file.ReadAllText(filePath) strRanges := strings.SplitSeq(input, SeparatorCharacter) - rngs := []Range{} - - for r := range strRanges { - parts := strings.Split(strings.TrimSpace(r), "-") - start, _ := strconv.ParseInt(parts[0], 10, 64) - end, _ := strconv.ParseInt(parts[1], 10, 64) - rng := Range{ - Start: start, - End: end, - } - rngs = append(rngs, rng) - } - total := int64(0) - for _, rng := range rngs { - for id := rng.Start; id <= rng.End; id++ { - idStr := strconv.FormatInt(id, 10) - idLength := len(idStr) - - if idLength%2 != 0 { - continue - } - - midpoint := idLength / 2 - - firstHalf := idStr[:midpoint] - secondHalf := idStr[midpoint:] - - if firstHalf != secondHalf { - continue - } + for r := range strRanges { + rng := rnge.From(r) + for id := range rng.InvalidIds() { total += id } } diff --git a/cmd/02/rnge/rnge.go b/cmd/02/rnge/rnge.go new file mode 100644 index 0000000..daf830f --- /dev/null +++ b/cmd/02/rnge/rnge.go @@ -0,0 +1,67 @@ +// Package rnge provides a simple structure to represent a range with a start and end value. +package rnge + +import ( + "iter" + "strconv" + "strings" +) + +const RangeSeparatorCharacter = "-" + +type Range interface { + InvalidIds() iter.Seq[int64] + Start() int64 + End() int64 +} + +type rnge struct { + start int64 + end int64 +} + +func From(rngeStr string) Range { + parts := strings.Split(strings.TrimSpace(rngeStr), RangeSeparatorCharacter) + start, _ := strconv.ParseInt(parts[0], 10, 64) + end, _ := strconv.ParseInt(parts[1], 10, 64) + + return rnge{ + start: start, + end: end, + } +} + +func (r rnge) Start() int64 { + return r.start +} + +func (r rnge) End() int64 { + return r.end +} + +func (r rnge) InvalidIds() iter.Seq[int64] { + return func(yield func(int64) bool) { + for id := r.start; id <= r.end; id++ { + idStr := strconv.FormatInt(id, 10) + idLength := len(idStr) + + if idLength%2 != 0 { + continue + } + + midpoint := idLength / 2 + firstHalf := idStr[:midpoint] + secondHalf := idStr[midpoint:] + + if firstHalf != secondHalf { + continue + } + + ok := yield(id) + + if !ok { + return + } + } + } +} diff --git a/cmd/02/rnge/rnge_test.go b/cmd/02/rnge/rnge_test.go new file mode 100644 index 0000000..caf5cd7 --- /dev/null +++ b/cmd/02/rnge/rnge_test.go @@ -0,0 +1,57 @@ +package rnge_test + +import ( + "slices" + "testing" + + "github.com/StevanFreeborn/advent-of-code-2025/cmd/02/rnge" +) + +func TestFrom(t *testing.T) { + expectedStart := int64(1000) + expectedEnd := int64(2000) + + r := rnge.From("1000-2000") + + if r.Start() != expectedStart { + t.Errorf("expected start %d, got %d", expectedStart, r.Start()) + } + + if r.End() != expectedEnd { + t.Errorf("expected end %d, got %d", expectedEnd, r.End()) + } +} + +func TestStart(t *testing.T) { + expectedStart := int64(500) + + r := rnge.From("500-1500") + + if r.Start() != expectedStart { + t.Errorf("expected start %d, got %d", expectedStart, r.Start()) + } +} + +func TestEnd(t *testing.T) { + expectedEnd := int64(1500) + + r := rnge.From("500-1500") + + if r.End() != expectedEnd { + t.Errorf("expected end %d, got %d", expectedEnd, r.End()) + } +} + +func TestInvalidIds(t *testing.T) { + r := rnge.From("1000-1100") + expectedInvalidIds := []int64{1010} + resultInvalidIds := []int64{} + + for id := range r.InvalidIds() { + resultInvalidIds = append(resultInvalidIds, id) + } + + if slices.Equal(resultInvalidIds, expectedInvalidIds) == false { + t.Errorf("expected invalid IDs %v, got %v", expectedInvalidIds, resultInvalidIds) + } +}