adventofcode/2024/day21/main.go

163 lines
3.9 KiB
Go
Raw Normal View History

2024-12-21 14:54:14 +00:00
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
}