Skip to content

Commit

Permalink
day 21
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Lewis committed Dec 21, 2024
1 parent 35e609b commit 345151a
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 3 deletions.
5 changes: 5 additions & 0 deletions 21/input_21
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
208A
586A
341A
463A
593A
149 changes: 149 additions & 0 deletions 21/twentyone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package main

import (
"fmt"
"math"
"slices"
"strconv"
"strings"

"github.com/cdlewis/advent-of-code/util/aoc"
"github.com/cdlewis/advent-of-code/util/grid"
)

var testInput = `029A
980A
179A
456A
379A`

var keypad = grid.Grid[byte]([][]byte{
{'7', '8', '9'},
{'4', '5', '6'},
{'1', '2', '3'},
{'#', '0', 'A'},
})

var directionPad = [][]byte{
{'#', '^', 'A'},
{'<', 'v', '>'},
}

var changeToDirection = map[grid.Point]byte{
grid.UP: '^',
grid.DOWN: 'v',
grid.LEFT: '<',
grid.RIGHT: '>',
}

func main() {
input := strings.Split(aoc.GetInput(21, false, testInput), "\n")

total := 0
for _, row := range input {
key, _ := strconv.Atoi(row[:len(row)-1])
complexity := cost(row, -1)
total += (key * complexity)
}

fmt.Println(total == 195664513288128)
}

var cache = map[string]int{}

func cost(code string, robot int) int {
if result, ok := cache[code+strconv.Itoa(robot)]; ok {
return result
}

maze := keypad
if robot > 0 {
maze = directionPad
}

totalCost := 0
prev := 'A'
for _, curr := range code {
posA, _ := maze.Find(byte(prev))
posB, _ := maze.Find(byte(curr))

paths := allPaths(posA, posB, maze)
cheapestPath := math.MaxInt
for _, p := range paths {
if robot == -1 {
length := cost(p, 25)
if length < cheapestPath {
cheapestPath = length
}
} else if robot > 1 {
length := cost(p, robot-1)
if length < cheapestPath {
cheapestPath = length
}
} else {
if len(p) < cheapestPath {
cheapestPath = len(p)
}
}
}

totalCost += cheapestPath
prev = curr
}

cache[code+strconv.Itoa(robot)] = totalCost
return totalCost
}

type item struct {
path []grid.Point
seen []grid.Point
}

func allPaths(
a grid.Point,
b grid.Point,
maze grid.Grid[byte],
) []string {
var results [][]grid.Point
q := []item{{seen: []grid.Point{a}}}

for len(q) > 0 {
curr := q[0]
currHead := curr.seen[len(curr.seen)-1]
q = q[1:]

if currHead == b {
results = append(results, curr.path)
}

for _, d := range grid.Directions {
nextPos := currHead.Add(d)
if maze.GetOrElse(nextPos, '#') == '#' {
continue
}

if slices.Index(curr.seen, nextPos) != -1 {
continue
}

q = append(q, item{
path: append(slices.Clone(curr.path), d),
seen: append(slices.Clone(curr.seen), nextPos),
})
}
}

var adaptedResults []string
for _, r := range results {
var adaptedResult []byte
for _, i := range r {
adaptedResult = append(adaptedResult, changeToDirection[i])
}
adaptedResult = append(adaptedResult, 'A')

adaptedResults = append(adaptedResults, string(adaptedResult))
}

return adaptedResults
}
36 changes: 33 additions & 3 deletions util/grid/grid.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ func (p Point) Subtract(another Point) Point {
return SubtractPoints(p, another)
}

func (p Point) ToDirection() []Point {
var results []Point

if p[0] > 0 {
results = append(results, DOWN)
} else if p[0] < 0 {
results = append(results, UP)
}

if p[1] > 0 {
results = append(results, RIGHT)
} else if p[1] < 0 {
results = append(results, LEFT)
}

return results
}

func (p Point) RotateClockwise() Point {
switch p {
case LEFT:
Expand Down Expand Up @@ -48,7 +66,7 @@ func (p Point) RotateCounterClockwise() Point {
panic("impossible state")
}

type Grid[T any] [][]T
type Grid[T comparable] [][]T

func (g Grid[T]) ValidPoint(point Point) bool {
return ValidPointCoordinate(point, g)
Expand Down Expand Up @@ -81,6 +99,18 @@ func (g Grid[T]) GetAdjacent(point Point) []Point {
return result
}

func (g Grid[T]) Find(needle T) (Point, bool) {
for idx := range g {
for jdx := range g[idx] {
if g[idx][jdx] == needle {
return Point{idx, jdx}, true
}
}
}

return Point{}, false
}

func (g Grid[T]) Print() {
for _, i := range g {
for _, j := range i {
Expand Down Expand Up @@ -108,7 +138,7 @@ var DOWN = Point{1, 0}
var LEFT = Point{0, -1}
var RIGHT = Point{0, 1}

var Directions = [][2]int{UP, DOWN, LEFT, RIGHT}
var Directions = []Point{UP, DOWN, LEFT, RIGHT}

var DirectionsDiagonal = [][2]int{
{-1, -1}, {-1, 0}, {-1, 1},
Expand All @@ -132,7 +162,7 @@ var Directions3D = [][]int{
{0, 0, -1},
}

func ShortestUnweightedPath[U any](
func ShortestUnweightedPath[U comparable](
graph Grid[U],
start Point,
isEnd func(Point) bool,
Expand Down

0 comments on commit 345151a

Please sign in to comment.