implement day 17 rock falling logic

This commit is contained in:
ryan manseau 2024-01-04 00:38:09 -08:00
parent 490696c63d
commit 9f1499a1d3
2 changed files with 148 additions and 0 deletions

1
inputs/day17.tt Normal file
View File

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

147
src/day17.ml Normal file
View File

@ -0,0 +1,147 @@
open Containers
let example_lines = {|>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>|}
type shape =
| Row
| Plus
| Angle
| Col
| Square
let dir_of_char = function
| '<' -> Vec2.left
| '>' -> Vec2.right
| _ -> failwith "oof"
;;
let get_dir stream idx =
let idx = idx mod Array.length stream in
stream.(idx)
;;
(*[{
#
# # #
### # # ##
#### # ### # ##
row plus angle col square
}]*)
let shape_points shape pos =
let points =
match shape with
| Row -> [ 0, 0; 1, 0; 2, 0; 3, 0 ]
| Plus -> [ 0, 1; 1, 0; 1, 1; 1, 2; 2, 1 ]
| Angle -> [ 0, 0; 1, 0; 2, 0; 2, 1; 2, 2 ]
| Col -> [ 0, 0; 0, 1; 0, 2; 0, 3 ]
| Square -> [ 0, 0; 1, 0; 0, 1; 1, 1 ]
in
points |> List.map (fun point -> Vec2.(pos + of_tuple point))
;;
type cave =
{ grid : char Grid.t
; mutable height : int
; mutable rocks : (shape * Vec2.t) list
; mutable stream_idx : int
}
let init_cave max_height =
let grid = Grid.init ~width:7 ~height:max_height (Fun.const '.') in
{ grid; height = -1; rocks = []; stream_idx = 0 }
;;
let draw_cave cave = Grid.draw cave.grid ~rev_y:true (fun _ contents -> contents)
let place_shape cave shape pos =
cave.rocks <- (shape, pos) :: cave.rocks;
shape_points shape pos
|> List.iter (fun point ->
if cave.height < point.Vec2.y then cave.height <- point.y;
Grid.set_e cave.grid point '#')
;;
let can_place_shape cave shape pos =
shape_points shape pos
|> List.fold_while
(fun _ point ->
match cave.grid.Grid.%(point) with
| Some '.' -> true, `Continue
| _ -> false, `Stop)
false
;;
let drop_shape cave stream shape =
let rec drop pos =
let stream_pos = Vec2.(pos + get_dir stream cave.stream_idx) in
cave.stream_idx <- cave.stream_idx + 1;
let pos = if can_place_shape cave shape stream_pos then stream_pos else pos in
let drop_pos = Vec2.(pos + Vec2.up) in
if can_place_shape cave shape drop_pos
then drop drop_pos
else place_shape cave shape pos
in
drop Vec2.{ x = 2; y = Int.(cave.height + 4) }
;;
let%expect_test "Day 17" =
let stream = example_lines |> Iter.of_str |> Iter.map dir_of_char |> Iter.to_array in
let cave = init_cave 40 in
drop_shape cave stream Row;
drop_shape cave stream Plus;
drop_shape cave stream Angle;
drop_shape cave stream Col;
drop_shape cave stream Square;
drop_shape cave stream Row;
drop_shape cave stream Plus;
drop_shape cave stream Angle;
drop_shape cave stream Col;
drop_shape cave stream Square;
Printf.printf "height: %i\n" (cave.height + 1);
Printf.printf "%s" @@ draw_cave cave;
[%expect
{|
height: 17
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
.......
....#..
....#..
....##.
##..##.
######.
.###...
..#....
.####..
....##.
....##.
....#..
..#.#..
..#.#..
#####..
..###..
...#...
..####. |}]
;;