Merge pull request #4 from StevanFreeborn/stevanfreeborn/refactor/clean-up-day-two-part-one

refactor: clean up day two part one
This commit is contained in:
Stevan Freeborn
2025-12-03 21:48:29 -05:00
committed by GitHub
5 changed files with 152 additions and 45 deletions
+8 -45
View File
@@ -1,61 +1,24 @@
package main package main
import ( import (
"os"
"strconv"
"strings" "strings"
"github.com/StevanFreeborn/advent-of-code-2025/cmd/02/rnge"
"github.com/StevanFreeborn/advent-of-code-2025/internal/file"
) )
const SeparatorCharacter = "," const SeparatorCharacter = ","
const RangeSeparatorCharacter = "-"
type Range struct {
Start int64
End int64
}
func SolvePartOne(filePath string) int64 { func SolvePartOne(filePath string) int64 {
bytes, readErr := os.ReadFile(filePath) input := file.ReadAllText(filePath)
strRanges := strings.SplitSeq(input, SeparatorCharacter)
if readErr != nil {
return 0
}
strRanges := strings.SplitSeq(string(bytes), 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) total := int64(0)
for _, rng := range rngs { for r := range strRanges {
for id := rng.Start; id <= rng.End; id++ { rng := rnge.From(r)
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 id := range rng.InvalidIds() {
total += id total += id
} }
} }
+67
View File
@@ -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
}
}
}
}
+57
View File
@@ -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)
}
}
+10
View File
@@ -24,3 +24,13 @@ func ReadLines(filePath string) []string {
return lines return lines
} }
func ReadAllText(filePath string) string {
fileContent, readErr := os.ReadFile(filePath)
if readErr != nil {
return ""
}
return string(fileContent)
}
+10
View File
@@ -19,3 +19,13 @@ func TestReadLines(t *testing.T) {
t.Errorf("got %s but expected %s", result, expectedLines) t.Errorf("got %s but expected %s", result, expectedLines)
} }
} }
func TestReadAllText(t *testing.T) {
expectedText := "hello\r\nworld\r\n"
result := file.ReadAllText("test.txt")
if result != expectedText {
t.Errorf("got %q but expected %q", result, expectedText)
}
}