Files
adventofcode/2024/gareth/day21/day21.go
Gareth ba588cbc77 Day21
2025-01-20 17:32:23 +00:00

126 lines
2.8 KiB
Go

package day21
import (
"strconv"
"strings"
)
type coordinate struct {
row, col int
}
var numberPad = map[string]coordinate{
"7": {0, 0}, "8": {0, 1}, "9": {0, 2},
"4": {1, 0}, "5": {1, 1}, "6": {1, 2},
"1": {2, 0}, "2": {2, 1}, "3": {2, 2},
"0": {3, 1}, "A": {3, 2},
}
var robotPad = map[string]coordinate{
"^": {0, 1}, "A": {0, 2},
"<": {1, 0}, "v": {1, 1}, ">": {1, 2},
}
type cacheKey struct {
sequence string
iterations int
}
var memo = make(map[cacheKey]int)
func Part1(input string) int {
codes := parseInput(input)
numpadGraph := createGraph(numberPad, coordinate{3, 0})
dirpadGraph := createGraph(robotPad, coordinate{0, 0})
total := 0
for _, code := range codes {
codeInt, _ := strconv.Atoi(code[:len(code)-1])
total += codeInt * getLength(code, 3, true, numpadGraph, dirpadGraph)
}
return total
}
func Part2(input string) int {
codes := parseInput(input)
numpadGraph := createGraph(numberPad, coordinate{3, 0})
dirpadGraph := createGraph(robotPad, coordinate{0, 0})
total := 0
for _, code := range codes {
codeInt, _ := strconv.Atoi(code[:len(code)-1])
total += codeInt * getLength(code, 26, true, numpadGraph, dirpadGraph)
}
return total
}
func parseInput(input string) []string {
parts := strings.Split(input, "\n")
codes := []string{}
codes = append(codes, parts...)
return codes
}
func createGraph(keypad map[string]coordinate, invalidCoords coordinate) map[string]string {
graph := make(map[string]string)
for a, coordA := range keypad {
for b, coordB := range keypad {
x1, y1 := coordA.row, coordA.col
x2, y2 := coordB.row, coordB.col
path := strings.Repeat("<", max(0, y1-y2)) +
strings.Repeat("v", max(0, x2-x1)) +
strings.Repeat("^", max(0, x1-x2)) +
strings.Repeat(">", max(0, y2-y1))
if invalidCoords == (coordinate{x1, y2}) || invalidCoords == (coordinate{x2, y1}) {
path = reverseString(path)
}
graph[a+"->"+b] = path + "A"
}
}
return graph
}
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func getLength(sequence string, iterations int, firstIter bool, numpadGraph map[string]string, dirpadGraph map[string]string) int {
if iterations == 0 {
return len(sequence)
}
key := cacheKey{sequence: sequence, iterations: iterations}
if cachedResult, exists := memo[key]; exists {
return cachedResult
}
graph := numpadGraph
if !firstIter {
graph = dirpadGraph
}
totalLength := 0
prev := "A"
for _, char := range sequence {
graphKey := prev + "->" + string(char)
if subSequence, exists := graph[graphKey]; exists {
totalLength += getLength(subSequence, iterations-1, false, numpadGraph, dirpadGraph)
}
prev = string(char)
}
memo[key] = totalLength
return totalLength
}