163 lines
3.9 KiB
Go
163 lines
3.9 KiB
Go
|
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
|
||
|
}
|