parse day 14 grid

haven't implemented the falling sand yet, but theres a cool expect test
that draws the grid
This commit is contained in:
ryan committed 2023-10-31 17:04:20 -07:00
1 parent 98f47654f8
commit 61e3520ede
4 files changed
+240 -12

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
open Containers
type tile =
| Empty
| Rock
| Sand
[@@deriving show]
let parse_line line =
let open Utils.Parse in
let vec = Vec2.of_tuple <$> both int (char ',' *> int) in
let vec_list = sep_by (string " -> ") vec in
Result.get_or_failwith @@ parse_string ~consume:All vec_list line
;;
let draw_rocks grid points =
let open Grid in
let _ =
points
|> List.reduce (fun a b ->
iter_region grid a b (fun pos -> grid.%(pos) <- Rock);
b)
in
()
;;
let%expect_test "Day 14 example" =
let grid = Grid.init ~width:20 ~height:10 (fun _ -> Empty) in
[ "8,4 -> 8,6 -> 6,6"; "13,4 -> 12,4 -> 12,9 -> 4,9" ]
|> List.iter (fun line -> parse_line line |> draw_rocks grid);
Printf.printf "%s"
@@ Grid.draw grid (function
| Empty -> '.'
| Rock -> '#'
| Sand -> 'o');
[%expect
{|
....................
....................
....................
....................
........#...##......
........#...#.......
......###...#.......
............#.......
............#.......
....#########....... |}]
;;
+39 -12
View File
@@ -1,5 +1,4 @@
open Containers
open Vec2
type 'a t =
{ width : int
@@ -8,33 +7,43 @@ type 'a t =
}
[@@deriving show]
let grid_vec2_of_idx ~width ~idx =
let vec2_of_idx ~width ~idx =
let y = idx / width in
let x = idx mod width in
Vec2.of_tuple (x, y)
;;
let at (grid : 'a t) (point : Vec2.t) =
let idx_of_vec2 width vec = Vec2.(Int.((width * vec.y) + vec.x))
let in_bounds grid point =
let x, y = Vec2.to_tuple point in
if x >= 0 && x < grid.width && y >= 0 && y < grid.height
then Array.get_safe grid.items @@ Int.((grid.width * y) + x)
x >= 0 && x < grid.width && y >= 0 && y < grid.height
;;
let at grid point =
if in_bounds grid point
then Array.get_safe grid.items @@ idx_of_vec2 grid.width point
else None
;;
let at_e (grid : 'a t) (point : Vec2.t) =
Option.get_exn_or "out of bounds!" @@ at grid point
Option.get_exn_or "point out of bounds!" @@ at grid point
;;
let set_e grid point item = Array.set grid.items (idx_of_vec2 grid.width point) item
let ( .%() ) = at_e
let ( .%()<- ) = set_e
let find (grid : 'a t) pred =
let open Option.Infix in
let* idx, item = Array.find_idx pred grid.items in
Some (grid_vec2_of_idx ~width:grid.width ~idx, item)
Some (vec2_of_idx ~width:grid.width ~idx, item)
;;
let init ~width ~height init =
{ width
; height
; items = Array.init (width * height) (fun idx -> init @@ grid_vec2_of_idx ~width ~idx)
; items = Array.init (width * height) (fun idx -> init @@ vec2_of_idx ~width ~idx)
}
;;
@@ -54,10 +63,28 @@ let of_lines parse_char lines : 'a t =
| _ -> failwith "somethin fucd up"
;;
let iter grid callback =
for y = 0 to Int.(grid.height - 1) do
for x = 0 to Int.(grid.width - 1) do
callback @@ Vec2.of_tuple (x, y)
let iter_region grid a b callback =
let open Vec2 in
for y = min a.y b.y to max a.y b.y do
for x = min a.x b.x to max a.x b.x do
let pos = { x; y } in
if in_bounds grid pos then callback pos
done
done
;;
let iter grid callback =
let a = Vec2.of_tuple (0, 0) in
let b = Vec2.of_tuple (grid.width - 1, grid.height - 1) in
iter_region grid a b callback
;;
let draw grid printer =
let str = ref [] in
iter grid (fun point ->
let item = grid.%(point) in
let char = printer item in
str := !str @ [ char ];
if point.x = grid.width - 1 then str := !str @ [ '\n' ]);
String.of_list !str
;;
+5
View File
@@ -2,7 +2,12 @@ type 'a t [@@deriving show]
val at : 'a t -> Vec2.t -> 'a option
val at_e : 'a t -> Vec2.t -> 'a
val set_e : 'a t -> Vec2.t -> 'a -> unit
val ( .%() ) : 'a t -> Vec2.t -> 'a
val ( .%()<- ) : 'a t -> Vec2.t -> 'a -> unit
val init : width:int -> height:int -> (Vec2.t -> 'a) -> 'a t
val of_lines : (char -> 'a) -> string list -> 'a t
val find : 'a t -> ('a -> bool) -> (Vec2.t * 'a) option
val iter_region : 'a t -> Vec2.t -> Vec2.t -> (Vec2.t -> unit) -> unit
val iter : 'a t -> (Vec2.t -> unit) -> unit
val draw : 'a t -> ('a -> char) -> string