very slow solution to day 15 part 2 :)

could be sped up by doing math to find intesections points of the
borders but that sounds boring
This commit is contained in:
ryan 2023-11-09 14:23:41 -08:00
parent b89e9c05ef
commit 8d97e7601c
4 changed files with 69 additions and 11 deletions

View File

@ -1,4 +1,5 @@
open Containers
module VecTbl = Hashtbl.Make (Vec2)
type sensor =
{ pos : Vec2.t
@ -51,23 +52,72 @@ let bounds sensors =
|> Vec2.bounds max_dist
;;
let could_be_beacon sensors ignore_known pos =
sensors
|> List.fold_while
(fun _ s ->
let d = taxicab_dist pos s.pos in
if d <= s.dist && (ignore_known || not Vec2.(pos = s.beacon))
then false, `Stop
else true, `Continue)
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
let is_impossible pos =
sensors
|> List.map (fun s ->
let d = taxicab_dist pos s.pos in
if d <= s.dist && not Vec2.(pos = s.beacon) then 1 else 0)
|> List.reduce_exn ( + )
|> Int.sign
in
Vec2.fold_region
Vec2.{ x = lx; y = scan_row }
Vec2.{ x = hx; y = scan_row }
(fun acc pos -> acc + is_impossible pos)
(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
;;
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 =
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" ((mult * point.x) + point.y);
[%expect {| 11756174628223|}]
;;

View File

@ -1,10 +1,13 @@
(library
(name aoc)
(libraries re containers dune-site angstrom)
(libraries re containers iter dune-site angstrom)
(inline_tests)
(preprocess (pps
ppx_regexp
ppx_deriving.show
ppx_deriving.eq
ppx_deriving.ord
ppx_deriving_hash
ppx_expect
ppx_inline_test)))

View File

@ -4,6 +4,7 @@ type t =
{ x : int
; y : int
}
[@@deriving eq, ord, hash]
let pp (fmt : Format.formatter) v = Format.fprintf fmt "(%i, %i)" v.x v.y
let show v = Format.asprintf "%a" pp v
@ -17,7 +18,7 @@ let of_tuple (x, y) = { x; y }
let to_tuple { x; y } = x, y
let ( + ) a b = { x = a.x + b.x; y = a.y + b.y }
let ( - ) a b = { x = a.x - b.x; y = a.y - b.y }
let ( = ) a b = a.x = b.x && a.y = b.y
let ( = ) = equal
let abs a = Int.{ x = abs a.x; y = abs a.y }
let iter_region a b callback =
@ -52,3 +53,5 @@ let bounds padding points =
let hy = Int.(hy + padding) in
of_tuple (lx, ly), of_tuple (hx, hy)
;;
let in_bounds l h p = p.x >= l.x && p.x <= h.x && p.y >= l.y && p.y <= h.y

View File

@ -2,6 +2,7 @@ type t =
{ x : int
; y : int
}
[@@deriving eq, ord, hash]
val show : t -> string
val pp : Format.formatter -> t -> unit
@ -20,3 +21,4 @@ val abs : t -> t
val iter_region : t -> t -> (t -> unit) -> unit
val fold_region : t -> t -> ('a -> t -> 'a) -> 'a -> 'a
val bounds : int -> t list -> t * t
val in_bounds : t -> t -> t -> bool