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
|
|
|
}
|