diff --git a/2024/day21/input b/2024/day21/input new file mode 100644 index 0000000..280ea40 --- /dev/null +++ b/2024/day21/input @@ -0,0 +1,5 @@ +836A +540A +965A +480A +789A diff --git a/2024/day21/main.go b/2024/day21/main.go new file mode 100644 index 0000000..3552995 --- /dev/null +++ b/2024/day21/main.go @@ -0,0 +1,162 @@ +package main + +import ( + "fmt" + "strings" + + h "git.bullercodeworks.com/brian/adventofcode/helpers" +) + +func main() { + inp := h.StdinToStringSlice() + dirPad := make(map[string]h.Coordinate) + dirPad["A"] = h.Coordinate{X: 2, Y: 1} + dirPad["^"] = h.Coordinate{X: 1, Y: 1} + dirPad[">"] = h.Coordinate{X: 2, Y: 0} + dirPad["v"] = h.Coordinate{X: 1, Y: 0} + dirPad["<"] = h.Coordinate{X: 0, Y: 0} + + numPad := make(map[string]h.Coordinate) + numPad["A"] = h.Coordinate{X: 2, Y: 0} + numPad["0"] = h.Coordinate{X: 1, Y: 0} + numPad["1"] = h.Coordinate{X: 0, Y: 1} + numPad["2"] = h.Coordinate{X: 1, Y: 1} + numPad["3"] = h.Coordinate{X: 2, Y: 1} + numPad["4"] = h.Coordinate{X: 0, Y: 2} + numPad["5"] = h.Coordinate{X: 1, Y: 2} + numPad["6"] = h.Coordinate{X: 2, Y: 2} + numPad["7"] = h.Coordinate{X: 0, Y: 3} + numPad["8"] = h.Coordinate{X: 1, Y: 3} + numPad["9"] = h.Coordinate{X: 2, Y: 3} + fmt.Println("# Part 1") + fmt.Println(findOrders(inp, dirPad, numPad, 2)) + fmt.Println("") + fmt.Println("# Part 2") + fmt.Println(findOrders(inp, dirPad, numPad, 25)) +} + +func parseNum(line string) int { + var numLine string + for i := range line { + if line[i] >= '0' && line[i] <= '9' { + numLine = numLine + string(line[i]) + } + } + var num int + fmt.Sscanf(numLine, "%d", &num) + return num +} + +// findOrders takes: +// +// inp: The codes that need to be input +// dirPad: The direction pad description +// numPad: The number pad description +// bots: How many robots are operating directional pads between you and the numpad robot. +func findOrders(inp []string, dirPad, numPad map[string]h.Coordinate, bots int) int { + var count int + cache := make(map[string][]int) + for _, line := range inp { + code := strings.Split(line, "") + s := workPad(code, "A", numPad) + wrk := workBots(s, bots, 1, cache, dirPad) + count += parseNum(line) * wrk + } + return count +} + +func workPad(code []string, start string, pad map[string]h.Coordinate) []string { + curr := pad[start] + out := []string{} + for _, c := range code { + btn := pad[c] + dist := btn.Sub(curr) + var outV, outH []string + for i := 0; i < h.Abs(dist.X); i++ { + if dist.X >= 0 { + outH = append(outH, ">") + } else { + outH = append(outH, "<") + } + } + for i := 0; i < h.Abs(dist.Y); i++ { + if dist.Y >= 0 { + outV = append(outV, "^") + } else { + outV = append(outV, "v") + } + } + _, isNumPad := pad["0"] + if isNumPad { + if curr.Y == 0 && btn.X == 0 { + out = append(out, outV...) + out = append(out, outH...) + } else if (curr.X == 0 && btn.Y == 0) || dist.X < 0 { + out = append(out, outH...) + out = append(out, outV...) + } else if dist.X >= 0 { + out = append(out, outV...) + out = append(out, outH...) + } + } else { + if curr.X == 0 && btn.Y == 1 { + out = append(out, outH...) + out = append(out, outV...) + } else if curr.Y == 1 && btn.X == 0 { + out = append(out, outV...) + out = append(out, outH...) + } else if dist.X < 0 { + out = append(out, outH...) + out = append(out, outV...) + } else if dist.X >= 0 { + out = append(out, outV...) + out = append(out, outH...) + } + } + curr = btn + out = append(out, "A") + } + return out +} + +func workBots(inst []string, bots int, bot int, cache map[string][]int, dirPad map[string]h.Coordinate) int { + cacheKey := strings.Join(inst, "") + if v, ok := cache[cacheKey]; ok { + if v[bot-1] != 0 { + return v[bot-1] + } + } else { + cache[cacheKey] = make([]int, bots) + } + s := workPad(inst, "A", dirPad) + cache[cacheKey][0] = len(s) + if bot == bots { + return len(s) + } + sSteps := splitSteps(s) + var count int + for _, s := range sSteps { + c := workBots(s, bots, bot+1, cache, dirPad) + subCacheKey := strings.Join(s, "") + if _, ok := cache[subCacheKey]; !ok { + cache[subCacheKey] = make([]int, bots) + } + cache[subCacheKey][0] = c + count += c + } + cache[cacheKey][bot-1] = count + return count +} + +func splitSteps(s []string) [][]string { + var out [][]string + var c []string + for _, char := range s { + c = append(c, char) + if char == "A" { + out = append(out, c) + c = []string{} + } + } + return out +} diff --git a/2024/day21/testinput b/2024/day21/testinput new file mode 100644 index 0000000..4cf0c29 --- /dev/null +++ b/2024/day21/testinput @@ -0,0 +1,5 @@ +029A +980A +179A +456A +379A