From fa5bf2e85beb776b500a1f1e30347c1ce5161ecf Mon Sep 17 00:00:00 2001 From: Kharec Date: Sun, 14 Dec 2025 10:14:18 +0100 Subject: [PATCH] feat: refactor some code and solve part two --- internal/2015/DayFourteen/code.go | 86 +++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/internal/2015/DayFourteen/code.go b/internal/2015/DayFourteen/code.go index 1dd7a04..09f6f75 100644 --- a/internal/2015/DayFourteen/code.go +++ b/internal/2015/DayFourteen/code.go @@ -8,6 +8,17 @@ import ( "strings" ) +var reindeerPattern = regexp.MustCompile(`\w+ can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds\.`) + +const raceTime = 2503 + +type Reindeer struct { + Speed int + FlyTime int + RestTime int + Points int +} + func init() { registry.Register("2015D14", ParseInput, PartOne, PartTwo) } @@ -17,24 +28,37 @@ func ParseInput(filepath string) []string { return strings.Split(string(content), "\n") } -func calculateMaxDistance(data []string, time int) int { - maxDistance := 0 - pattern := regexp.MustCompile(`\w+ can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds\.`) +func parseReindeer(line string) Reindeer { + matches := reindeerPattern.FindStringSubmatch(line) + speed, _ := strconv.Atoi(matches[1]) + flyTime, _ := strconv.Atoi(matches[2]) + restTime, _ := strconv.Atoi(matches[3]) + return Reindeer{Speed: speed, FlyTime: flyTime, RestTime: restTime} +} +func parseReindeers(data []string) []Reindeer { + reindeers := make([]Reindeer, 0, len(data)) for _, line := range data { - matches := pattern.FindStringSubmatch(line) + reindeers = append(reindeers, parseReindeer(line)) + } + return reindeers +} - speed, _ := strconv.Atoi(matches[1]) - flyTime, _ := strconv.Atoi(matches[2]) - restTime, _ := strconv.Atoi(matches[3]) - cycleTime := flyTime + restTime +func (reindeer Reindeer) distanceAtTime(time int) int { + cycleTime := reindeer.FlyTime + reindeer.RestTime + fullCycles := time / cycleTime + distance := fullCycles * reindeer.Speed * reindeer.FlyTime + remainingTime := time % cycleTime + distance += reindeer.Speed * min(remainingTime, reindeer.FlyTime) + return distance +} - fullCycles := time / cycleTime - distance := fullCycles * speed * flyTime - - remainingTime := time % cycleTime - distance += speed * min(remainingTime, flyTime) +func calculateMaxDistance(data []string, time int) int { + reindeers := parseReindeers(data) + maxDistance := 0 + for _, reindeer := range reindeers { + distance := reindeer.distanceAtTime(time) if distance > maxDistance { maxDistance = distance } @@ -43,10 +67,42 @@ func calculateMaxDistance(data []string, time int) int { return maxDistance } +func calculateMaxPoints(data []string, time int) int { + reindeers := parseReindeers(data) + + for second := 1; second <= time; second++ { + maxDistance := 0 + distances := make([]int, len(reindeers)) + + for idx := range reindeers { + distance := reindeers[idx].distanceAtTime(second) + distances[idx] = distance + if distance > maxDistance { + maxDistance = distance + } + } + + for idx := range reindeers { + if distances[idx] == maxDistance { + reindeers[idx].Points++ + } + } + } + + maxPoints := 0 + for idx := range reindeers { + if reindeers[idx].Points > maxPoints { + maxPoints = reindeers[idx].Points + } + } + + return maxPoints +} + func PartOne(data []string) int { - return calculateMaxDistance(data, 2503) + return calculateMaxDistance(data, raceTime) } func PartTwo(data []string) int { - return 0 + return calculateMaxPoints(data, raceTime) }