aoc2024/day-18/internal/one/solve.go

81 lines
1.6 KiB
Go
Raw Normal View History

2024-12-18 18:48:11 +00:00
package one
import (
"bytes"
"math"
"github.com/onyx-and-iris/aoc2024/day-18/internal/config"
"github.com/onyx-and-iris/aoc2024/day-18/internal/point"
2024-12-18 18:48:11 +00:00
"github.com/onyx-and-iris/aoc2024/day-18/internal/queue"
log "github.com/sirupsen/logrus"
orderedmap "github.com/wk8/go-ordered-map/v2"
2024-12-18 18:48:11 +00:00
)
var ShortestPath *orderedmap.OrderedMap[point.Point, struct{}]
2024-12-18 18:48:11 +00:00
func Solve(buf []byte, config config.Config) (int, error) {
r := bytes.NewReader(buf)
graph, err := parseLines(r, config)
if err != nil {
return 0, err
}
log.Debugf("start: %v end: %v", graph.start, graph.end)
log.Debugf("\n%s\n", graph.String())
queue := queue.New[point.Point]()
2024-12-18 18:48:11 +00:00
queue.Enqueue(graph.start)
visited := make(map[point.Point]struct{})
costs := make(map[point.Point]int)
prev := make(map[point.Point]point.Point)
2024-12-18 18:48:11 +00:00
for !queue.IsEmpty() {
current := queue.Dequeue()
if current == graph.end {
break
}
_, ok := visited[current]
if ok {
continue
}
visited[current] = struct{}{}
for _, n := range neighbours(current) {
if graph.isOutOfBounds(n) {
continue
}
if graph.valueAt(n) == '#' {
continue
}
_, ok := costs[n]
if !ok {
costs[n] = math.MaxInt
}
new_cost := costs[current] + 1
if new_cost < costs[n] {
costs[n] = new_cost
prev[n] = current
queue.Enqueue(n)
}
}
}
ShortestPath = orderedmap.New[point.Point, struct{}]()
ShortestPath.Set(graph.end, struct{}{})
2024-12-18 18:48:11 +00:00
node := prev[graph.end]
for node != graph.start {
ShortestPath.Set(node, struct{}{})
2024-12-18 18:48:11 +00:00
node = prev[node]
}
log.Debugf("\n%s\n", graph.debug(ShortestPath))
return ShortestPath.Len(), nil
2024-12-18 18:48:11 +00:00
}