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