6x speed up on 24 day 16 part 2

We filter out already visited states when adding them to the work list.

We also don't sort the work list as we're already generating it in a
sorted (by cost) order.
This commit is contained in:
2024-12-16 13:57:13 +00:00
parent bfd65557bf
commit 4bc7815851

View File

@@ -15,10 +15,7 @@ let rec dijkstra visit check_end states =
| (cost, state) :: t -> | (cost, state) :: t ->
if check_end state then Some (cost, state, t) if check_end state then Some (cost, state, t)
else else
let new_states = let new_states = visit cost state |> List.merge compare_costs t in
visit cost state |> List.sort compare_costs
|> List.merge compare_costs t
in
dijkstra visit check_end new_states dijkstra visit check_end new_states
let visited_idx grid ((dx, dy), p) = let visited_idx grid ((dx, dy), p) =
@@ -45,21 +42,23 @@ let visit grid visited_grid cost state =
(cost + 1000, ((dy, -dx), p) :: state); (cost + 1000, ((dy, -dx), p) :: state);
]) ])
let visit_max grid visited_grid max_cost cost state = let has_visited grid visited_grid (cost, state) =
let has_visited = visited_grid.(visited_idx grid (List.hd state)) < cost in visited_grid.(visited_idx grid (List.hd state)) < cost
let visit_max grid visited_grid cost state =
let (dx, dy), ((x, y) as p) = List.hd state in let (dx, dy), ((x, y) as p) = List.hd state in
if has_visited then [] if has_visited grid visited_grid (cost, state) then []
else if cost > max_cost then []
else if Aoc.Grid.get_by_pos grid p = '#' then [] else if Aoc.Grid.get_by_pos grid p = '#' then []
else ( else (
(*Printf.printf "%d (%d, %d)\n" cost x y; Printf.printf "%d (%d, %d)\n" cost x y;
flush stdout;*) flush stdout;
visited_grid.(visited_idx grid (List.hd state)) <- cost; visited_grid.(visited_idx grid (List.hd state)) <- cost;
[ [
(cost + 1, ((dx, dy), (x + dx, y + dy)) :: state); (cost + 1, ((dx, dy), (x + dx, y + dy)) :: state);
(cost + 1000, ((-dy, dx), p) :: state); (cost + 1000, ((-dy, dx), p) :: state);
(cost + 1000, ((dy, -dx), p) :: state); (cost + 1000, ((dy, -dx), p) :: state);
]) ]
|> List.filter (fun x -> not (has_visited grid visited_grid x)))
let[@warning "-32"] print_point (x, y) = Printf.printf "(%d, %d)" x y let[@warning "-32"] print_point (x, y) = Printf.printf "(%d, %d)" x y
@@ -80,13 +79,10 @@ let part1 (grid, start_pos) =
let part2 (grid, start_pos) = let part2 (grid, start_pos) =
let cost = part1 (grid, start_pos) in let cost = part1 (grid, start_pos) in
let visited_grid = Array.make (Aoc.Grid.length grid * 4) max_int in let visited_grid = Array.make (Aoc.Grid.length grid * 4) cost in
let rec impl acc lst = let rec impl acc lst =
match match
dijkstra dijkstra (visit_max grid visited_grid) (check_end2 grid visited_grid) lst
(visit_max grid visited_grid cost)
(check_end2 grid visited_grid)
lst
with with
| None -> acc | None -> acc
| Some (_, states, remainder) -> | Some (_, states, remainder) ->