faster 15.2 solution with line intersections :/

This commit is contained in:
ryan 2023-11-10 01:13:16 -08:00
parent 8d97e7601c
commit 705c9e9a7c

View File

@ -1,5 +1,4 @@
open Containers
module VecTbl = Hashtbl.Make (Vec2)
type sensor =
{ pos : Vec2.t
@ -53,8 +52,9 @@ let bounds sensors =
;;
let could_be_beacon sensors ignore_known pos =
sensors
|> List.fold_while
let open Iter in
of_list sensors
|> fold_while
(fun _ s ->
let d = taxicab_dist pos s.pos in
if d <= s.dist && (ignore_known || not Vec2.(pos = s.beacon))
@ -63,61 +63,103 @@ let could_be_beacon sensors ignore_known pos =
true
;;
let%expect_test "Day 15.1" =
let sensors = Utils.lines_of_input 15 |> List.map parse_sensor in
let scan_row = 2000000 in
let Vec2.{ x = lx; _ }, Vec2.{ x = hx; _ } = bounds sensors in
Vec2.fold_region
Vec2.{ x = lx; y = scan_row }
Vec2.{ x = hx; y = scan_row }
(fun acc pos -> if could_be_beacon sensors false pos then acc else acc + 1)
0
|> Printf.printf "%i\n";
[%expect {| 5525990 |}]
;;
(* let%expect_test "Day 15.1" = *)
(* let sensors = Utils.lines_of_input 15 |> List.map parse_sensor in *)
(* let scan_row = 2000000 in *)
(* let Vec2.{ x = lx; _ }, Vec2.{ x = hx; _ } = bounds sensors in *)
(* Vec2.fold_region *)
(* Vec2.{ x = lx; y = scan_row } *)
(* Vec2.{ x = hx; y = scan_row } *)
(* (fun acc pos -> if could_be_beacon sensors false pos then acc else acc + 1) *)
(* 0 *)
(* |> Printf.printf "%i\n"; *)
(* [%expect {| 5525990 |}] *)
(* ;; *)
let points_on_border tbl sensor =
let points = ref [] in
let dist = sensor.dist + 1 in
for d1 = 0 to dist do
let d2 = dist - d1 in
let open Vec2 in
let p1 = of_tuple (d1, d2) in
let p2 = of_tuple (d1, Int.(-d2)) in
let new_points =
[ sensor.pos + p1; sensor.pos - p1; sensor.pos + p2; sensor.pos - p2 ]
|> List.fold_left
(fun acc point ->
match VecTbl.mem tbl point with
| true -> point :: acc
| false ->
VecTbl.add tbl point ();
acc)
[]
in
points := !points @ new_points
done;
!points
;;
(* module VecTbl = Hashtbl.Make (Vec2) *)
(* let points_on_border tbl sensor = *)
(* let points = ref [] in *)
(* let dist = sensor.dist + 1 in *)
(* for d1 = 0 to dist do *)
(* let d2 = dist - d1 in *)
(* let open Vec2 in *)
(* let p1 = of_tuple (d1, d2) in *)
(* let p2 = of_tuple (d1, Int.(-d2)) in *)
(* let new_points = *)
(* [ sensor.pos + p1; sensor.pos - p1; sensor.pos + p2; sensor.pos - p2 ] *)
(* |> List.fold_left *)
(* (fun acc point -> *)
(* match VecTbl.find_opt tbl point with *)
(* | Some false -> acc *)
(* | Some true -> *)
(* VecTbl.replace tbl point false; *)
(* point :: acc *)
(* | None -> *)
(* VecTbl.add tbl point true; *)
(* acc) *)
(* [] *)
(* in *)
(* points := !points @ new_points *)
(* done; *)
(* !points *)
(* ;; *)
(* let%expect_test "Day 15.2 brute force" = *)
(* let sensors = Utils.lines_of_input 15 |> List.map parse_sensor in *)
(* let mult = 4000000 in *)
(* let range = mult in *)
(* let in_bounds = Vec2.(in_bounds origin @@ of_tuple (range, range)) in *)
(* let tbl = VecTbl.create (range * 10) in *)
(* let point = *)
(* sensors *)
(* |> Iter.of_list *)
(* |> Iter.flat_map_l @@ points_on_border tbl *)
(* |> Iter.fold_while *)
(* (fun _ v -> *)
(* if in_bounds v && could_be_beacon sensors true v *)
(* then Some v, `Stop *)
(* else None, `Continue) *)
(* None *)
(* |> Option.get_exn_or "fucc :(" *)
(* in *)
(* Printf.printf "%i\n" ((mult * point.x) + point.y); *)
(* [%expect {| 11756174628223 |}] *)
(* ;; *)
module IntSet = Set.Make (Int)
let%expect_test "Day 15.2" =
let sensors = Utils.lines_of_input 15 |> List.map parse_sensor in
let mult = 4000000 in
let range = mult in
let in_bounds = Vec2.(in_bounds origin @@ of_tuple (range, range)) in
let tbl = VecTbl.create (range * 10) in
let point =
let pos_coeffs, neg_coeffs =
sensors
|> Iter.of_list
|> Iter.flat_map_l @@ points_on_border tbl
|> Iter.fold_while
(fun _ v ->
if in_bounds v && could_be_beacon sensors true v
then Some v, `Stop
|> Iter.fold
(fun (pos_coeffs, neg_coeffs) { pos; beacon = _; dist } ->
let p1 = pos.y - pos.x + dist + 1 in
let p2 = pos.y - pos.x - dist - 1 in
let n1 = pos.y + pos.x + dist + 1 in
let n2 = pos.y + pos.x - dist - 1 in
Iter.(
( append pos_coeffs (of_list [ p1; p2 ])
, append neg_coeffs (of_list [ n1; n2 ]) )))
(Iter.empty, Iter.empty)
in
let point =
let open Iter in
product pos_coeffs neg_coeffs
|> fold_while
(fun _ (p, n) ->
let i = Vec2.of_tuple ((n - p) / 2, (n + p) / 2) in
if in_bounds i && could_be_beacon sensors true i
then Some i, `Stop
else None, `Continue)
None
|> Option.get_exn_or "fucc :("
|> Option.get_exn_or "no distress beacon found :("
in
Printf.printf "%i" ((mult * point.x) + point.y);
[%expect {| 11756174628223|}]
Printf.printf "%i\n" ((mult * point.x) + point.y);
[%expect {| 11756174628223 |}]
;;