mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2025-01-10 06:40:47 +00:00
90 lines
1.7 KiB
Go
90 lines
1.7 KiB
Go
package two
|
|
|
|
import (
|
|
hp "container/heap"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/onyx-and-iris/aoc2024/day-16/internal/one"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type graph struct {
|
|
start node
|
|
end node
|
|
data []string
|
|
}
|
|
|
|
func newGraph() *graph {
|
|
return &graph{}
|
|
}
|
|
|
|
func (g *graph) String() string {
|
|
return strings.Join(g.data, "\n")
|
|
}
|
|
|
|
func (g *graph) valueAt(n node) rune {
|
|
return rune(g.data[n.y][n.x])
|
|
}
|
|
|
|
func (g *graph) dijkstra() int {
|
|
heap := newHeap()
|
|
hp.Push(heap, move{g.start, 0, []node{g.start}})
|
|
visited := make(map[node]int)
|
|
const turnCost int = 1000
|
|
|
|
lowestCostPaths := [][]node{}
|
|
for heap.Len() > 0 {
|
|
current := hp.Pop(heap).(move)
|
|
|
|
// we're on a path that's already exceeded the lowest cost
|
|
if current.cost > one.LowestCost {
|
|
continue
|
|
}
|
|
|
|
if g.valueAt(current.node) == 'E' {
|
|
lowestCostPaths = append(lowestCostPaths, current.path)
|
|
continue
|
|
}
|
|
|
|
if v, ok := visited[current.node]; ok {
|
|
if v < current.cost {
|
|
continue
|
|
}
|
|
}
|
|
visited[current.node] = current.cost
|
|
|
|
for _, n := range neighbours(current.node) {
|
|
if g.valueAt(current.node) == '#' {
|
|
continue
|
|
}
|
|
|
|
next_cost := current.cost + 1
|
|
if n.direction != current.node.direction {
|
|
next_cost += turnCost
|
|
}
|
|
|
|
hp.Push(heap, newMove(n, next_cost, append(slices.Clone(current.path), n)))
|
|
}
|
|
}
|
|
|
|
possibleSafe := make(map[coords]struct{})
|
|
for _, path := range lowestCostPaths {
|
|
for _, n := range path {
|
|
possibleSafe[n.coords] = struct{}{}
|
|
}
|
|
}
|
|
|
|
log.Debugf("\n%s\n", g.debug(possibleSafe))
|
|
|
|
return len(possibleSafe)
|
|
}
|
|
|
|
func (g *graph) debug(possibleSafe map[coords]struct{}) string {
|
|
temp := slices.Clone(g.data)
|
|
for n := range possibleSafe {
|
|
temp[n.y] = replaceAtIndex(temp[n.y], 'O', n.x)
|
|
}
|
|
return strings.Join(temp, "\n")
|
|
}
|