faster 15.2 solution with line intersections :/
This commit is contained in:
parent
8d97e7601c
commit
705c9e9a7c
138
src/day15.ml
138
src/day15.ml
|
|
@ -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 |}]
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user