From 3c078ace91312248c13e273fb9d37bd5825170a0 Mon Sep 17 00:00:00 2001 From: alexchao26 Date: Sat, 26 Dec 2020 18:31:34 -0500 Subject: [PATCH] 2015-day14: reindeers running & stopping --- 2015/day14/main.go | 89 +++++++++++++++++++++++++++++++++++++++++ 2015/day14/main_test.go | 26 ++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 2015/day14/main.go create mode 100644 2015/day14/main_test.go diff --git a/2015/day14/main.go b/2015/day14/main.go new file mode 100644 index 0000000..120e23e --- /dev/null +++ b/2015/day14/main.go @@ -0,0 +1,89 @@ +package main + +import ( + "flag" + "fmt" + "strings" + + "github.com/alexchao26/advent-of-code-go/mathutil" + + "github.com/alexchao26/advent-of-code-go/util" +) + +func main() { + var part int + flag.IntVar(&part, "part", 1, "part 1 or 2") + flag.Parse() + fmt.Println("Running part", part) + + ans := reindeerOlympics(util.ReadFile("./input.txt"), part) + fmt.Println("Output:", ans) +} + +func reindeerOlympics(input string, part int) int { + reindeerToDistanceMap := map[string][]int{} + + for _, line := range strings.Split(input, "\n") { + var name string + var speed, runTime, restTime int + _, err := fmt.Sscanf(line, "%s can fly %d km/s for %d seconds, but then must rest for %d seconds.", &name, &speed, &runTime, &restTime) + if err != nil { + panic(err) + } + + // 1-index the distances slice, indices line up with elapsed time + reindeerToDistanceMap[name] = append(reindeerToDistanceMap[name], 0) + + var dist int + remainingRunTime := runTime + remainingRestTime := restTime + for t := 0; t < 2503; t++ { + if remainingRunTime > 0 { + dist += speed + remainingRunTime-- + } else { + remainingRestTime-- + if remainingRestTime == 0 { + remainingRunTime = runTime + remainingRestTime = restTime + } + } + reindeerToDistanceMap[name] = append(reindeerToDistanceMap[name], dist) + } + } + + // for part 1 return the furthest end distance (time 2503 seconds) + if part == 1 { + var furthest int + for _, distSli := range reindeerToDistanceMap { + furthest = mathutil.MaxInt(distSli[2503], furthest) + } + return furthest + } + + // for part 2, score each second, then find the highest score + reindeerScores := map[string]int{} + for sec := 1; sec <= 2503; sec++ { + var names []string + var bestDist int + for name, distanceSli := range reindeerToDistanceMap { + if distanceSli[sec] > bestDist { + names = []string{name} + bestDist = distanceSli[sec] + } else if distanceSli[sec] == bestDist { + names = append(names, name) + } + } + + for _, name := range names { + reindeerScores[name]++ + } + } + + var bestScore int + for _, v := range reindeerScores { + bestScore = mathutil.MaxInt(bestScore, v) + } + + return bestScore +} diff --git a/2015/day14/main_test.go b/2015/day14/main_test.go new file mode 100644 index 0000000..f5c4019 --- /dev/null +++ b/2015/day14/main_test.go @@ -0,0 +1,26 @@ +package main + +import ( + "testing" + + "github.com/alexchao26/advent-of-code-go/util" +) + +func Test_reindeerOlympics(t *testing.T) { + tests := []struct { + name string + input string + part int + want int + }{ + {"part1 actual", util.ReadFile("input.txt"), 1, 2660}, + {"part2 actual", util.ReadFile("input.txt"), 2, 1256}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := reindeerOlympics(tt.input, tt.part); got != tt.want { + t.Errorf("reindeerOlympics() = %v, want %v", got, tt.want) + } + }) + } +}