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" "github.com/onyx-and-iris/aoc2024/day-18/internal/queue" log "github.com/sirupsen/logrus" orderedmap "github.com/wk8/go-ordered-map/v2" ) var ShortestPath *orderedmap.OrderedMap[point.Point, struct{}] 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]() queue.Enqueue(graph.start) visited := make(map[point.Point]struct{}) costs := make(map[point.Point]int) prev := make(map[point.Point]point.Point) 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{}{}) node := prev[graph.end] for node != graph.start { ShortestPath.Set(node, struct{}{}) node = prev[node] } log.Debugf("\n%s\n", graph.debug(ShortestPath)) return ShortestPath.Len(), nil }