2024 day 16 part 2
Quite slow takes ~11 mins to run.
This commit is contained in:
@@ -5,15 +5,15 @@ let find grid c =
|
|||||||
|
|
||||||
let input_of_file fname =
|
let input_of_file fname =
|
||||||
let grid = Aoc.Grid.of_file fname in
|
let grid = Aoc.Grid.of_file fname in
|
||||||
let start_state = (find grid 'S', (1, 0)) in
|
let start_pos = find grid 'S' in
|
||||||
(grid, start_state)
|
(grid, start_pos)
|
||||||
|
|
||||||
let rec dijkstra visit check_end states =
|
let rec dijkstra visit check_end states =
|
||||||
let compare_costs (lhs, _) (rhs, _) = compare lhs rhs in
|
let compare_costs (lhs, _) (rhs, _) = compare lhs rhs in
|
||||||
match states with
|
match states with
|
||||||
| [] -> failwith "dijkstra"
|
| [] -> None
|
||||||
| (cost, state) :: t ->
|
| (cost, state) :: t ->
|
||||||
if check_end state then cost
|
if check_end state then Some (cost, state, t)
|
||||||
else
|
else
|
||||||
let new_states =
|
let new_states =
|
||||||
visit cost state |> List.sort compare_costs
|
visit cost state |> List.sort compare_costs
|
||||||
@@ -21,7 +21,7 @@ let rec dijkstra visit check_end states =
|
|||||||
in
|
in
|
||||||
dijkstra visit check_end new_states
|
dijkstra visit check_end new_states
|
||||||
|
|
||||||
let visited_idx grid (p, (dx, dy)) =
|
let visited_idx grid ((dx, dy), p) =
|
||||||
let add =
|
let add =
|
||||||
match (dx, dy) with
|
match (dx, dy) with
|
||||||
| 1, 0 -> 0
|
| 1, 0 -> 0
|
||||||
@@ -32,27 +32,69 @@ let visited_idx grid (p, (dx, dy)) =
|
|||||||
in
|
in
|
||||||
(Aoc.Grid.idx_of_pos grid p * 4) + add
|
(Aoc.Grid.idx_of_pos grid p * 4) + add
|
||||||
|
|
||||||
let has_visited grid visited_grid state = visited_grid.(visited_idx grid state)
|
let visit grid visited_grid cost state =
|
||||||
|
let (dx, dy), ((x, y) as p) = List.hd state in
|
||||||
let mark_visited grid visited_grid state =
|
let has_visited = visited_grid.(visited_idx grid (List.hd state)) in
|
||||||
visited_grid.(visited_idx grid state) <- true
|
if has_visited then []
|
||||||
|
|
||||||
let visit grid visited_grid cost ((((x, y) as p), (dx, dy)) as state) =
|
|
||||||
if has_visited grid visited_grid state 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 %d %d\n" cost x y dx dy;
|
visited_grid.(visited_idx grid (List.hd state)) <- true;
|
||||||
mark_visited grid visited_grid state;
|
|
||||||
[
|
[
|
||||||
(cost + 1, ((x + dx, y + dy), (dx, dy)));
|
(cost + 1, ((dx, dy), (x + dx, y + dy)) :: state);
|
||||||
(cost + 1000, (p, (-dy, dx)));
|
(cost + 1000, ((-dy, dx), p) :: state);
|
||||||
(cost + 1000, (p, (dy, -dx)));
|
(cost + 1000, ((dy, -dx), p) :: state);
|
||||||
])
|
])
|
||||||
|
|
||||||
let check_end grid (p, _) = Aoc.Grid.get_by_pos grid p = 'E'
|
let visit_max grid visited_grid max_cost cost state =
|
||||||
|
let has_visited = visited_grid.(visited_idx grid (List.hd state)) < cost in
|
||||||
|
let (dx, dy), ((x, y) as p) = List.hd state in
|
||||||
|
if has_visited then []
|
||||||
|
else if cost > max_cost then []
|
||||||
|
else if Aoc.Grid.get_by_pos grid p = '#' then []
|
||||||
|
else (
|
||||||
|
(*Printf.printf "%d (%d, %d)\n" cost x y;
|
||||||
|
flush stdout;*)
|
||||||
|
visited_grid.(visited_idx grid (List.hd state)) <- cost;
|
||||||
|
[
|
||||||
|
(cost + 1, ((dx, dy), (x + dx, y + dy)) :: state);
|
||||||
|
(cost + 1000, ((-dy, dx), p) :: state);
|
||||||
|
(cost + 1000, ((dy, -dx), p) :: state);
|
||||||
|
])
|
||||||
|
|
||||||
let part (grid, start_state) =
|
let[@warning "-32"] print_point (x, y) = Printf.printf "(%d, %d)" x y
|
||||||
|
|
||||||
|
let check_end grid state =
|
||||||
|
let _, p = List.hd state in
|
||||||
|
Aoc.Grid.get_by_pos grid p = 'E'
|
||||||
|
|
||||||
|
let check_end2 grid _ state = check_end grid state
|
||||||
|
|
||||||
|
let part1 (grid, start_pos) =
|
||||||
let visited_grid = Array.make (Aoc.Grid.length grid * 4) false in
|
let visited_grid = Array.make (Aoc.Grid.length grid * 4) false in
|
||||||
dijkstra (visit grid visited_grid) (check_end grid) [ (0, start_state) ]
|
match
|
||||||
|
dijkstra (visit grid visited_grid) (check_end grid)
|
||||||
|
[ (0, [ ((1, 0), start_pos) ]) ]
|
||||||
|
with
|
||||||
|
| None -> failwith "part"
|
||||||
|
| Some (cost, _, _) -> cost
|
||||||
|
|
||||||
let _ = Aoc.main input_of_file [ (string_of_int, part) ]
|
let part2 (grid, start_pos) =
|
||||||
|
let cost = part1 (grid, start_pos) in
|
||||||
|
let visited_grid = Array.make (Aoc.Grid.length grid * 4) max_int in
|
||||||
|
let rec impl acc lst =
|
||||||
|
match
|
||||||
|
dijkstra
|
||||||
|
(visit_max grid visited_grid cost)
|
||||||
|
(check_end2 grid visited_grid)
|
||||||
|
lst
|
||||||
|
with
|
||||||
|
| None -> acc
|
||||||
|
| Some (_, states, remainder) ->
|
||||||
|
List.iter (fun x -> visited_grid.(visited_idx grid x) <- 0) states;
|
||||||
|
impl (states :: acc) remainder
|
||||||
|
in
|
||||||
|
impl [] [ (0, [ ((1, 0), start_pos) ]) ]
|
||||||
|
|> List.concat |> List.map snd |> List.sort_uniq compare |> List.length
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
Aoc.main input_of_file [ (string_of_int, part1); (string_of_int, part2) ]
|
||||||
|
Reference in New Issue
Block a user