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
|
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 |}]
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user