modify djikstra to work without a goal

if you give None as a goal, then it traverses the entire grid and finds
the shortest path to every node. the distances can then be queried via the
get_info that is passed in as an argument
This commit is contained in:
ryan 2023-11-22 15:02:43 -08:00
parent ae2acb87fa
commit 360be1a368
2 changed files with 28 additions and 6 deletions

View File

@ -67,12 +67,33 @@ let path_distance grid goal start_nodes =
let%expect_test "Day 12.1" =
let grid, goal, start_nodes = parse_grid false in
Printf.printf "%i" @@ path_distance grid goal start_nodes;
Printf.printf "%i" @@ path_distance grid (Some goal) start_nodes;
[%expect {| 497 |}]
;;
let%expect_test "Day 12.2" =
let grid, goal, start_nodes = parse_grid true in
Printf.printf "%i" @@ path_distance grid goal start_nodes;
Printf.printf "%i" @@ path_distance grid (Some goal) start_nodes;
[%expect {| 492 |}]
;;
let%expect_test "Day 12 test" =
let grid, goal, start_nodes = parse_grid false in
let _ = path_distance grid None start_nodes in
let print_dist_to pos =
let node = Option.get_exn_or "invalid pos!" grid.Grid.%(pos) in
Printf.printf "%s %c %i\n" (Vec2.show pos) node.char node.distance
in
print_dist_to goal;
print_dist_to Vec2.(goal + right);
print_dist_to Vec2.(goal + down);
print_dist_to Vec2.(of_tuple (121, 23));
print_dist_to Vec2.(origin + right);
[%expect
{|
(149, 20) E 497
(150, 20) z 498
(149, 21) y 496
(121, 23) a 138
(1, 0) b 21 |}]
;;

View File

@ -64,14 +64,15 @@ let djikstra ~eq ~get_info ~set_info ~get_weight ~get_neighbors ~goal ~start_nod
let b_dist, _ = get_info b in
Int.compare a_dist b_dist)
!seen;
match !seen with
| next :: _ when eq next goal ->
match goal, !seen with
| Some goal_node, next :: _ when eq goal_node next ->
let dist, _ = get_info next in
Some dist
| next :: rest ->
| None, [] -> Some 0
| _, next :: rest ->
seen := rest;
djikstra' next
| [] -> None
| Some _, [] -> None
in
List.iter (fun node -> set_info node (0, false)) start_nodes;
match start_nodes with