Use binary search for 2024 day 18 part 2.
This dramatically speeds the search up (by ~100x).
This commit is contained in:
@@ -110,12 +110,31 @@ let part1 count rocks =
|
|||||||
[grid] which makes it impossible to get from the top-left to bottom-right.
|
[grid] which makes it impossible to get from the top-left to bottom-right.
|
||||||
*)
|
*)
|
||||||
let part2 start_count grid =
|
let part2 start_count grid =
|
||||||
let rec impl count =
|
(* Implementation notes:
|
||||||
match find_route_length count grid with
|
|
||||||
| None -> count
|
We do this by binary search in impl. The left_count is a known count of
|
||||||
| Some _ -> impl (count + 1)
|
rocks that is passable, right_count is a known count that is impassable.
|
||||||
|
|
||||||
|
Once left_count + 1 = right_count we know that right_count is the first
|
||||||
|
rock to fall that causes the route to be blocked.
|
||||||
|
|
||||||
|
count_rocks is used to find the number of rocks (and so give an initial
|
||||||
|
right_count).
|
||||||
|
*)
|
||||||
|
let rec count_rocks acc idx =
|
||||||
|
if idx >= Array.length grid.grid then acc
|
||||||
|
else if grid.grid.(idx) = max_int then count_rocks acc (idx + 1)
|
||||||
|
else count_rocks (max acc grid.grid.(idx)) (idx + 1)
|
||||||
in
|
in
|
||||||
let count = impl start_count in
|
let rec impl left_count right_count =
|
||||||
|
if right_count - left_count = 1 then right_count
|
||||||
|
else
|
||||||
|
let count = (left_count + right_count) / 2 in
|
||||||
|
match find_route_length count grid with
|
||||||
|
| None -> impl left_count count
|
||||||
|
| Some _ -> impl count right_count
|
||||||
|
in
|
||||||
|
let count = impl start_count (1 + count_rocks 0 0) in
|
||||||
match Array.find_index (( = ) (count - 1)) grid.grid with
|
match Array.find_index (( = ) (count - 1)) grid.grid with
|
||||||
| None -> failwith "part2"
|
| None -> failwith "part2"
|
||||||
| Some idx -> idx
|
| Some idx -> idx
|
||||||
|
Reference in New Issue
Block a user