Compare commits

...
3 Commits
Author SHA1 Message Date
ryan 8ec58edd08 solve day 18!
it was kinda ez
2024-02-13 23:03:04 -08:00
ryan 1904239ca7 reorganize day 17 code a bit 2024-01-11 10:48:11 -08:00
ryan 46d49dc3fe add pretty printed tower test in day 17 2024-01-11 10:19:39 -08:00
6 changed files with 2220 additions and 42 deletions

No files matched your search

+2025
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -37,7 +37,8 @@ let reachable f t =
let get_neighbors grid node_pos =
let node = Grid.at_e grid node_pos in
Vec2.directions
|> List.filter_map (fun dir ->
|> Iter.of_list
|> Iter.filter_map (fun dir ->
let neighbor_pos = Vec2.(node_pos + dir) in
match Grid.at grid neighbor_pos with
| Some neighbor when reachable node.char neighbor.char -> Some neighbor_pos
+2 -1
View File
@@ -47,9 +47,10 @@ let parse_valves lines =
~get_weight:(fun _ _ -> 1)
~get_neighbors:(fun room ->
match Hashtbl.get rooms room with
| Some (_, tunnels) -> tunnels
| Some (_, tunnels) -> Iter.of_list tunnels
| None -> failwith "sad")
~start_nodes:[ from ]
()
%> Option.get_exn_or "big sad")
in
valves
+68 -39
View File
@@ -11,16 +11,6 @@ let dir_of_char = function
let next_stream_idx stream idx = (idx + 1) mod Array.length stream
type shape =
| Row
| Plus
| Angle
| Col
| Square
let next_shape_idx idx = (idx + 1) mod 5
let get_shape idx = [| Row; Plus; Angle; Col; Square |].(idx)
(*[{
#
# # #
@@ -30,6 +20,15 @@ let get_shape idx = [| Row; Plus; Angle; Col; Square |].(idx)
row plus angle col square
}]*)
type shape =
| Row
| Plus
| Angle
| Col
| Square
let get_shape idx = [| Row; Plus; Angle; Col; Square |].(idx mod 5)
let shape_points shape pos =
let points =
match shape with
@@ -42,35 +41,38 @@ let shape_points shape pos =
points |> List.map (fun point -> Vec2.(pos + of_tuple point))
;;
type cache_key =
{ stream_idx : int
; rock_idx : int
type loop_key =
{ rock : shape
; stream_idx : int
; normalized_topo : int array
}
type loop =
{ rock_idx : int
; height : int
}
type cave =
{ grid : char Grid.t
; loop_cache : (cache_key, int * int) Hashtbl.t
; mutable grid_topo : int array
; mutable grid_height : int
; mutable height : int
; mutable rock_idx : int
; total_rocks : int
; mutable rocks : int
; mutable stream_idx : int
; mutable dropped_rocks : int
; mutable remaining_rocks : int
; loop_cache : (loop_key, loop) Hashtbl.t
; mutable height : int
}
let init_cave max_height remaining_rocks =
let init_cave max_height total_rocks =
let grid = Grid.init ~width:7 ~height:max_height (Fun.const '.') in
{ grid
; height = -1
; grid_height = -1
; rock_idx = 0
; dropped_rocks = 0
; rocks = 0
; stream_idx = 0
; grid_topo = Array.init cave_width (Fun.const 0)
; loop_cache = Hashtbl.create max_height
; remaining_rocks
; total_rocks
}
;;
@@ -99,7 +101,7 @@ let can_place_shape cave shape pos =
;;
let drop_shape cave stream =
let shape = get_shape cave.rock_idx in
let shape = get_shape cave.rocks in
let rec drop pos =
let stream_pos = Vec2.(pos + stream.(cave.stream_idx)) in
cave.stream_idx <- next_stream_idx stream cave.stream_idx;
@@ -109,9 +111,7 @@ let drop_shape cave stream =
then drop drop_pos
else place_shape cave shape pos
in
cave.rock_idx <- next_shape_idx cave.rock_idx;
cave.dropped_rocks <- cave.dropped_rocks + 1;
cave.remaining_rocks <- cave.remaining_rocks - 1;
cave.rocks <- cave.rocks + 1;
drop Vec2.{ x = 2; y = Int.(cave.grid_height + 4) }
;;
@@ -121,24 +121,24 @@ let normalize_topo topo =
;;
let rec drop_shapes cave stream =
let cache_key =
{ rock_idx = cave.rock_idx
let loop_key =
{ rock = get_shape cave.rocks
; stream_idx = cave.stream_idx
; normalized_topo = normalize_topo cave.grid_topo
}
in
match Hashtbl.get cave.loop_cache cache_key with
| Some (cached_height, cached_dropped_rocks)
when let rock_delta = cave.dropped_rocks - cached_dropped_rocks in
rock_delta < cave.remaining_rocks ->
let rock_delta = cave.dropped_rocks - cached_dropped_rocks in
let height_delta = cave.height - cached_height in
cave.height <- cave.height + height_delta;
cave.dropped_rocks <- cave.dropped_rocks + rock_delta;
cave.remaining_rocks <- cave.remaining_rocks - rock_delta;
let remaining_rocks cave = cave.total_rocks - cave.rocks in
let loop_rocks loop = cave.rocks - loop.rock_idx in
let loop_fits loop = loop_rocks loop < remaining_rocks cave in
match Hashtbl.get cave.loop_cache loop_key with
| Some loop when loop_fits loop ->
let loop_height = cave.height - loop.height in
cave.height <- cave.height + loop_height;
cave.rocks <- cave.rocks + loop_rocks loop;
drop_shapes cave stream
| _ when cave.remaining_rocks > 0 ->
Hashtbl.add cave.loop_cache cache_key (cave.height, cave.dropped_rocks);
| _ when remaining_rocks cave > 0 ->
let loop = { height = cave.height; rock_idx = cave.rocks } in
Hashtbl.add cave.loop_cache loop_key loop;
drop_shape cave stream;
drop_shapes cave stream
| _ -> ()
@@ -170,3 +170,32 @@ let%expect_test "Day 17.2" =
Printf.printf "height: %i\n" @@ solve 1_000_000_000_000 (Utils.lines_of_input 17);
[%expect {| height: 1597714285698 |}]
;;
let%expect_test "Smol tower" =
let stream =
example_lines |> List.hd |> Iter.of_str |> Iter.map dir_of_char |> Iter.to_array
in
let cave = init_cave 18 8 in
drop_shapes cave stream;
Printf.printf "%s" @@ draw_cave cave;
[%expect
{|
.......
.......
.......
.....#.
.....#.
..####.
.###...
..#....
.####..
....##.
....##.
....#..
..#.#..
..#.#..
#####..
..###..
...#...
..####. |}]
;;
+121
View File
@@ -0,0 +1,121 @@
open Containers
let example_lines =
String.lines
{|2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5|}
;;
module Vec3 = struct
type t = int * int * int [@@deriving show, eq, ord, hash]
let directions = [ 1, 0, 0; -1, 0, 0; 0, 1, 0; 0, -1, 0; 0, 0, 1; 0, 0, -1 ]
let ( + ) (x1, y1, z1) (x2, y2, z2) = x1 + x2, y1 + y2, z1 + z2
let ( - ) (x1, y1, z1) (x2, y2, z2) = x1 - x2, y1 - y2, z1 - z2
let ( = ) = equal
let iter_region (ax, ay, az) (bx, by, bz) callback =
for z = az to bz do
for y = ay to by do
for x = ax to bx do
let p = x, y, z in
callback p
done
done
done
;;
let in_bounds (lx, ly, lz) (hx, hy, hz) (x, y, z) =
not (x < lx || x > hx || y < ly || y > hy || z < lz || z > hz)
;;
let find_bounds points =
let first = Iter.head_exn points in
let padding = 1, 1, 1 in
let min, max =
points
|> Iter.drop 1
|> Iter.fold
(fun ((lx, ly, lz), (hx, hy, hz)) (x, y, z) ->
(min lx x, min ly y, min lz z), (max hx x, max hy y, max hz z))
(first, first)
in
min - padding, max + padding
;;
end
module Vec3Set = Set.Make (Vec3)
let parse_points lines =
lines
|> List.map (fun line ->
match List.map Int.of_string_exn Re.(matches (Pcre.regexp {|\d+|}) line) with
| [ x; y; z ] -> x, y, z
| _ -> failwith "oopzi doopers")
|> Vec3Set.of_list
;;
let solve_part_1 lines =
let points = parse_points lines in
let min, max = Vec3.find_bounds @@ Vec3Set.to_iter points in
let surface_area = ref 0 in
Vec3.iter_region min max (fun point ->
if not @@ Vec3Set.mem point points
then
Vec3.directions
|> List.iter (fun dir ->
let n = Vec3.(point + dir) in
if Vec3Set.mem n points then incr surface_area));
!surface_area
;;
let%expect_test "Day 18.1 example" =
Format.printf "%i" @@ solve_part_1 example_lines;
[%expect {| 64 |}]
;;
let%expect_test "Day 18.1" =
Format.printf "%i" @@ solve_part_1 @@ Utils.lines_of_input 18;
[%expect {| 3662 |}]
;;
let solve_part_2 lines =
let points = parse_points lines in
let min, max = Vec3.find_bounds @@ Vec3Set.to_iter points in
let in_bounds = Vec3.in_bounds min max in
let surface_area = ref 0 in
let directions_iter = Iter.of_list Vec3.directions in
let get_neighbors point =
directions_iter
|> Iter.map Vec3.(fun dir -> point + dir)
|> Iter.filter (fun neighbor ->
let in_droplet = Vec3Set.mem neighbor points in
if in_droplet then incr surface_area;
(not in_droplet) && in_bounds neighbor)
in
let _ignore =
Utils.djikstra_hash ~get_weight:(fun _ _ -> 1) ~get_neighbors ~start_nodes:[ min ] ()
in
!surface_area
;;
let%expect_test "Day 18.2 example" =
Format.printf "%i" @@ solve_part_2 example_lines;
[%expect {| 58 |}]
;;
let%expect_test "Day 18.2" =
Format.printf "%i" @@ solve_part_2 @@ Utils.lines_of_input 18;
[%expect {| 2060 |}]
;;
+2 -1
View File
@@ -50,7 +50,7 @@ let djikstra ~eq ~get_info ~set_info ~get_weight ~get_neighbors ~goal ~start_nod
let c_dist, _ = get_info c_node in
set_info c_node (c_dist, true);
get_neighbors c_node
|> List.iter (fun neighbor ->
|> Iter.iter (fun neighbor ->
let n_dist, n_visited = get_info neighbor in
if not n_visited
then (
@@ -90,6 +90,7 @@ let djikstra_hash
~get_weight
~get_neighbors
~start_nodes
()
=
let module Tbl =
CCHashtbl.Make (struct