adventofcode/2024/day16/main.go

125 lines
2.3 KiB
Go
Raw Normal View History

2024-12-17 17:12:36 +00:00
package main
import (
"fmt"
2024-12-17 18:47:16 +00:00
"math"
2024-12-17 17:12:36 +00:00
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
2024-12-17 18:47:16 +00:00
inp := h.StdinToCoordMap()
2024-12-17 17:12:36 +00:00
start, _ := inp.FindFirst('S')
end, _ := inp.FindFirst('E')
2024-12-17 18:47:16 +00:00
score, seats := bfs(inp, start, end)
fmt.Println("# Part 1")
fmt.Println("Minimum Score:", score)
fmt.Println("# Part 2")
fmt.Println("Best Seats:", seats)
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
func bfs(inp h.CoordByteMap, s, e h.Coordinate) (int, int) {
start := CD{c: s, d: E}
minScore := math.MaxInt
queue := []State{
{
pos: start,
path: []h.Coordinate{},
},
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
visited := make(map[CD]int)
sizeToC := make(map[int][]h.Coordinate)
2024-12-17 17:12:36 +00:00
2024-12-17 18:47:16 +00:00
for len(queue) > 0 {
currState := queue[0]
queue = queue[1:]
2024-12-17 17:12:36 +00:00
2024-12-17 18:47:16 +00:00
if currState.score > minScore {
continue
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
if currState.pos.c.Equals(e) {
if currState.score <= minScore {
minScore = currState.score
sizeToC[minScore] = append(sizeToC[minScore], currState.path...)
}
continue
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
for _, n := range currState.pos.GetNeighbors() {
if inp.Get(n.c) == '#' {
continue
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
score := currState.score + 1
if currState.pos.d != n.d {
score += 1000
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
if prev, ok := visited[n]; ok {
if prev < score {
continue
}
}
visited[n] = score
np := make([]h.Coordinate, len(currState.path))
copy(np, currState.path)
queue = append(queue, State{
pos: n,
path: append(np, n.c),
score: score,
})
2024-12-17 17:12:36 +00:00
}
}
2024-12-17 18:47:16 +00:00
seatMap := make(map[h.Coordinate]bool)
for _, p := range sizeToC[minScore] {
seatMap[p] = true
}
/*
for y := inp.TLY; y <= inp.BRY; y++ {
for x := inp.TLX; x <= inp.BRX; x++ {
c := h.Coordinate{X: x, Y: y}
if _, ok := seatMap[c]; ok {
fmt.Print("O")
} else {
fmt.Print(string(inp.Get(c)))
}
}
fmt.Println()
}
*/
return minScore, len(seatMap) + 1
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
var (
N = h.Coordinate{X: 0, Y: -1}
E = h.Coordinate{X: 1, Y: 0}
S = h.Coordinate{X: 0, Y: 1}
W = h.Coordinate{X: -1, Y: 0}
Dirs = []h.Coordinate{N, E, S, W}
)
2024-12-17 17:12:36 +00:00
2024-12-17 18:47:16 +00:00
type CD struct {
c, d h.Coordinate
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
func (cd CD) GetNeighbors() []CD {
var ret []CD
opp := h.Coordinate{X: -cd.d.X, Y: -cd.d.Y}
for _, dir := range Dirs {
if !dir.Equals(opp) {
ret = append(ret, CD{
c: cd.c.Add(dir),
d: dir,
})
}
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
return ret
2024-12-17 17:12:36 +00:00
}
2024-12-17 18:47:16 +00:00
type State struct {
pos CD
path []h.Coordinate
score int
2024-12-17 17:12:36 +00:00
}