solve day 14!
This commit is contained in:
parent
ceb0f04a78
commit
ceaebf895d
311
src/day14.ml
311
src/day14.ml
|
|
@ -10,7 +10,7 @@ type tile =
|
||||||
| Path_R
|
| Path_R
|
||||||
|
|
||||||
let char_of_tile = function
|
let char_of_tile = function
|
||||||
| Empty -> ' '
|
| Empty -> '_'
|
||||||
| Rock -> '#'
|
| Rock -> '#'
|
||||||
| Sand -> 'o'
|
| Sand -> 'o'
|
||||||
| Start -> 'v'
|
| Start -> 'v'
|
||||||
|
|
@ -19,6 +19,11 @@ let char_of_tile = function
|
||||||
| Path_R -> '\\'
|
| Path_R -> '\\'
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
let is_sand = function
|
||||||
|
| Sand -> true
|
||||||
|
| _ -> false
|
||||||
|
;;
|
||||||
|
|
||||||
let parse_line line =
|
let parse_line line =
|
||||||
let open Utils.Parse in
|
let open Utils.Parse in
|
||||||
let vec = Vec2.of_tuple <$> both int (char ',' *> int) in
|
let vec = Vec2.of_tuple <$> both int (char ',' *> int) in
|
||||||
|
|
@ -52,10 +57,13 @@ let parse_grid lines start =
|
||||||
lx, hx, ly, hy)
|
lx, hx, ly, hy)
|
||||||
(Int.max_int, 0, Int.max_int, 0)
|
(Int.max_int, 0, Int.max_int, 0)
|
||||||
in
|
in
|
||||||
|
let pad_floor = 1 in
|
||||||
let pad_x = 2 in
|
let pad_x = 2 in
|
||||||
|
let height = 1 + hy - ly + pad_floor in
|
||||||
|
let lx = min lx (start.x - height) in
|
||||||
|
let hx = max hx (start.x + height) in
|
||||||
|
let width = 1 + hx - lx + (pad_x * 2) in
|
||||||
let extra = Vec2.of_tuple (lx - pad_x, ly) in
|
let extra = Vec2.of_tuple (lx - pad_x, ly) in
|
||||||
let width = hx - lx + (pad_x * 2) + 1 in
|
|
||||||
let height = hy - ly + 1 in
|
|
||||||
let start = Vec2.(start - extra) in
|
let start = Vec2.(start - extra) in
|
||||||
let open Grid in
|
let open Grid in
|
||||||
let grid = init ~width ~height (fun _ -> Empty) in
|
let grid = init ~width ~height (fun _ -> Empty) in
|
||||||
|
|
@ -65,7 +73,7 @@ let parse_grid lines start =
|
||||||
grid, start
|
grid, start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec drop_sand grid start draw_path =
|
let rec drop_sand_abyss draw_path grid start =
|
||||||
let d = Vec2.(start + down) in
|
let d = Vec2.(start + down) in
|
||||||
let l = Vec2.(d + left) in
|
let l = Vec2.(d + left) in
|
||||||
let r = Vec2.(d + right) in
|
let r = Vec2.(d + right) in
|
||||||
|
|
@ -73,242 +81,107 @@ let rec drop_sand grid start draw_path =
|
||||||
match grid.%(start), grid.%(l), grid.%(d), grid.%(r) with
|
match grid.%(start), grid.%(l), grid.%(d), grid.%(r) with
|
||||||
| _, _, Some Empty, _ ->
|
| _, _, Some Empty, _ ->
|
||||||
if draw_path then grid.%(d) <- Path_D;
|
if draw_path then grid.%(d) <- Path_D;
|
||||||
drop_sand grid d draw_path
|
drop_sand_abyss draw_path grid d
|
||||||
| _, Some Empty, _, _ ->
|
| _, Some Empty, _, _ ->
|
||||||
if draw_path then grid.%(l) <- Path_L;
|
if draw_path then grid.%(l) <- Path_L;
|
||||||
drop_sand grid l draw_path
|
drop_sand_abyss draw_path grid l
|
||||||
| _, _, _, Some Empty ->
|
| _, _, _, Some Empty ->
|
||||||
if draw_path then grid.%(r) <- Path_R;
|
if draw_path then grid.%(r) <- Path_R;
|
||||||
drop_sand grid r draw_path
|
drop_sand_abyss draw_path grid r
|
||||||
| _, _, None, _ -> Error ()
|
| _, _, None, _ -> Error ()
|
||||||
| Some Empty, _, _, _ ->
|
| Some Empty, _, _, _ ->
|
||||||
grid.%(start) <- Sand;
|
grid.%(start) <- Sand;
|
||||||
Ok ()
|
Ok ()
|
||||||
| _, _, _, _ -> failwith "pain"
|
| _, _, _, _ -> failwith "oh no!"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec drop_all_sand grid start =
|
let rec drop_sand_floor grid start =
|
||||||
match drop_sand grid start false with
|
let d = Vec2.(start + down) in
|
||||||
| Ok () -> drop_all_sand grid start
|
let l = Vec2.(d + left) in
|
||||||
|
let r = Vec2.(d + right) in
|
||||||
|
let open Grid in
|
||||||
|
match grid.%(start), grid.%(l), grid.%(d), grid.%(r) with
|
||||||
|
| _, _, Some Empty, _ -> drop_sand_floor grid d
|
||||||
|
| _, Some Empty, _, _ -> drop_sand_floor grid l
|
||||||
|
| _, _, _, Some Empty -> drop_sand_floor grid r
|
||||||
|
| Some Empty, _, _, _ ->
|
||||||
|
grid.%(start) <- Sand;
|
||||||
|
Ok ()
|
||||||
|
| Some Start, _, _, _ ->
|
||||||
|
grid.%(start) <- Sand;
|
||||||
|
Error ()
|
||||||
|
| _, _, _, _ -> failwith "ooooo!"
|
||||||
|
;;
|
||||||
|
|
||||||
|
let rec drop_all_sand drop grid start =
|
||||||
|
match drop grid start with
|
||||||
|
| Ok () -> drop_all_sand drop grid start
|
||||||
| Error _ -> ()
|
| Error _ -> ()
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let%expect_test "Day 14 example" =
|
let%expect_test "Day 14.1 example" =
|
||||||
let lines = [ "498,4 -> 498,6 -> 496,6"; "503,4 -> 502,4 -> 502,9 -> 494,9" ] in
|
let lines = [ "498,4 -> 498,6 -> 496,6"; "503,4 -> 502,4 -> 502,9 -> 494,9" ] in
|
||||||
let start = Vec2.of_tuple (500, 0) in
|
let start = Vec2.of_tuple (500, 0) in
|
||||||
let grid, start = parse_grid lines start in
|
let grid, start = parse_grid lines start in
|
||||||
let show_grid () = Printf.printf "%s" @@ Grid.draw grid char_of_tile in
|
drop_all_sand (drop_sand_abyss false) grid start;
|
||||||
show_grid ();
|
let _ = drop_sand_abyss true grid start in
|
||||||
|
let count = Grid.count grid is_sand in
|
||||||
|
Printf.printf "%i grains\n%s" count @@ Grid.draw grid char_of_tile;
|
||||||
[%expect
|
[%expect
|
||||||
{|
|
{|
|
||||||
v
|
24 grains
|
||||||
|
_____________v_____________
|
||||||
|
_____________|_____________
|
||||||
|
____________/o_____________
|
||||||
# ##
|
___________/ooo____________
|
||||||
# #
|
__________/#ooo##__________
|
||||||
### #
|
_________/o#ooo#___________
|
||||||
#
|
________/###ooo#___________
|
||||||
#
|
________|__oooo#___________
|
||||||
######### |}];
|
_______/o_ooooo#___________
|
||||||
drop_all_sand grid start;
|
______/#########___________
|
||||||
let _ = drop_sand grid start true in
|
______|____________________ |}]
|
||||||
show_grid ();
|
|
||||||
[%expect
|
|
||||||
{|
|
|
||||||
v
|
|
||||||
|
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
/#ooo##
|
|
||||||
/o#ooo#
|
|
||||||
/###ooo#
|
|
||||||
| oooo#
|
|
||||||
/o ooooo#
|
|
||||||
/######### |}]
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let%expect_test "Day 14 example" =
|
let%expect_test "Day 14.2 example" =
|
||||||
|
let lines = [ "498,4 -> 498,6 -> 496,6"; "503,4 -> 502,4 -> 502,9 -> 494,9" ] in
|
||||||
|
let start = Vec2.of_tuple (500, 0) in
|
||||||
|
let grid, start = parse_grid lines start in
|
||||||
|
drop_all_sand drop_sand_floor grid start;
|
||||||
|
let count = Grid.count grid is_sand in
|
||||||
|
Printf.printf "%i grains\n%s" count @@ Grid.draw grid char_of_tile;
|
||||||
|
[%expect
|
||||||
|
{|
|
||||||
|
93 grains
|
||||||
|
_____________o_____________
|
||||||
|
____________ooo____________
|
||||||
|
___________ooooo___________
|
||||||
|
__________ooooooo__________
|
||||||
|
_________oo#ooo##o_________
|
||||||
|
________ooo#ooo#ooo________
|
||||||
|
_______oo###ooo#oooo_______
|
||||||
|
______oooo_oooo#ooooo______
|
||||||
|
_____oooooooooo#oooooo_____
|
||||||
|
____ooo#########ooooooo____
|
||||||
|
___ooooo_______ooooooooo___ |}]
|
||||||
|
;;
|
||||||
|
|
||||||
|
let%expect_test "Day 14.1" =
|
||||||
let lines = Utils.lines_of_input 14 in
|
let lines = Utils.lines_of_input 14 in
|
||||||
let start = Vec2.of_tuple (500, 0) in
|
let start = Vec2.of_tuple (500, 0) in
|
||||||
let grid, start = parse_grid lines start in
|
let grid, start = parse_grid lines start in
|
||||||
drop_all_sand grid start;
|
drop_all_sand (drop_sand_abyss false) grid start;
|
||||||
let _ = drop_sand grid start true in
|
let count = Grid.count grid is_sand in
|
||||||
Printf.printf "%s" @@ Grid.draw grid char_of_tile;
|
Printf.printf "%i" count;
|
||||||
[%expect
|
[%expect {| 683 |}]
|
||||||
{|
|
;;
|
||||||
v
|
|
||||||
|
|
let%expect_test "Day 14.2" =
|
||||||
|
|
let lines = Utils.lines_of_input 14 in
|
||||||
|
|
let start = Vec2.of_tuple (500, 0) in
|
||||||
|
|
let grid, start = parse_grid lines start in
|
||||||
|
|
drop_all_sand drop_sand_floor grid start;
|
||||||
|
|
let count = Grid.count grid is_sand in
|
||||||
|
|
Printf.printf "%i" count;
|
||||||
|
|
[%expect {| 28821 |}]
|
||||||
oo\
|
|
||||||
oooo\
|
|
||||||
oooooo\
|
|
||||||
oooooooo\
|
|
||||||
ooo#oo#ooo\
|
|
||||||
oooo#oo#oooo\
|
|
||||||
#######oo######\
|
|
||||||
# oooo #o\
|
|
||||||
# oooooo #oo\
|
|
||||||
# oooooooo #ooo\
|
|
||||||
# oooooooooo #oooo\
|
|
||||||
# oooooooooooo#ooooo\
|
|
||||||
#ooooooooooooo#oooooo\
|
|
||||||
#ooooooooooooo#ooooooo\
|
|
||||||
###############oooooooo\
|
|
||||||
oooooooooo\
|
|
||||||
oooooooooooo\
|
|
||||||
######oooooooo\
|
|
||||||
oooooooooo\
|
|
||||||
###### ######oooooo\
|
|
||||||
oooooooo\
|
|
||||||
###### ###### ######oooo\
|
|
||||||
oooooo\
|
|
||||||
###### ###### ###### ######oo\
|
|
||||||
oooo\
|
|
||||||
###### ###### ###### ###### ######\
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
/# #
|
|
||||||
/o# #
|
|
||||||
/#o# #
|
|
||||||
/o#o# #
|
|
||||||
/#o#o# #
|
|
||||||
|#o#o# #
|
|
||||||
|#o#o# #
|
|
||||||
|#o#o# #
|
|
||||||
|#######
|
|
||||||
|
|
|
||||||
oo\
|
|
||||||
#ooo\
|
|
||||||
#oooo\
|
|
||||||
# #ooooo\
|
|
||||||
# #ooo#o#\
|
|
||||||
# #ooo#o#|
|
|
||||||
# # #ooo#o#|
|
|
||||||
# # #o#o#o#|
|
|
||||||
# # #o#o#o#|
|
|
||||||
# # #o#o#o#|
|
|
||||||
# # #o#o#o#|
|
|
||||||
###########|
|
|
||||||
oo\
|
|
||||||
oooo\
|
|
||||||
#oooo#\
|
|
||||||
#oooo#|
|
|
||||||
#oooo#|
|
|
||||||
#########oooo##\
|
|
||||||
# oooooo#|
|
|
||||||
# ooooooo#|
|
|
||||||
# oooooooo#|
|
|
||||||
# ooooooooo#|
|
|
||||||
###############|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
#oo\
|
|
||||||
# #ooo\
|
|
||||||
# # #oooo\
|
|
||||||
# # #ooo#o\
|
|
||||||
# # #ooo#o#\
|
|
||||||
# # #o#o#o#o\
|
|
||||||
# # #o#o#o#o#\
|
|
||||||
# # # #o#o#o#o#|
|
|
||||||
# # # #o#o#o#o#o\
|
|
||||||
# # # #o#o#o#o#oo\
|
|
||||||
###############ooo\
|
|
||||||
ooooo\
|
|
||||||
ooooooo\
|
|
||||||
# ooooooooo\
|
|
||||||
#############\
|
|
||||||
oo\
|
|
||||||
oooo\
|
|
||||||
######\
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/######
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/###### ######
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/###### ###### ######
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/###### ###### ###### ######
|
|
||||||
|
|
|
||||||
|
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
/#oooo#
|
|
||||||
/o######
|
|
||||||
/ooo
|
|
||||||
/ooooo
|
|
||||||
/#ooooo#
|
|
||||||
|#ooooo#
|
|
||||||
/o#ooooo#
|
|
||||||
/oo#ooooo#
|
|
||||||
/####ooooo#######
|
|
||||||
|# ooooooo #
|
|
||||||
|# ooooooooo #
|
|
||||||
|#ooooooooooo #
|
|
||||||
|#oooooooooooo #
|
|
||||||
|#ooooooooooooo #
|
|
||||||
|################
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
/ooooo
|
|
||||||
/oo#ooo#
|
|
||||||
/ooo#####
|
|
||||||
/ooooo
|
|
||||||
/ooooooo
|
|
||||||
/oo#oooo#o
|
|
||||||
/ooo#oooo#oo
|
|
||||||
/oooo#oooo#ooo
|
|
||||||
/######oooo#########
|
|
||||||
|# oooooo #
|
|
||||||
|# oooooooo #
|
|
||||||
|# oooooooooo #
|
|
||||||
/o# oooooooooooo #
|
|
||||||
/oo###################
|
|
||||||
/oooo
|
|
||||||
/oooooo
|
|
||||||
/######oo
|
|
||||||
| oooo
|
|
||||||
| oooooo
|
|
||||||
| ######oo
|
|
||||||
| oooo
|
|
||||||
/o###### ######
|
|
||||||
/ooo
|
|
||||||
/###### ###### ######
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
# oo\
|
|
||||||
# oooo\
|
|
||||||
# oooo#o\
|
|
||||||
#ooo#o#o#\
|
|
||||||
#ooo#o#o#|
|
|
||||||
#o#o#o#o#|
|
|
||||||
#o#o#o#o#|
|
|
||||||
#o#o#o#o#|
|
|
||||||
#o#o#o#o#|
|
|
||||||
#########|
|
|
||||||
oo\
|
|
||||||
oooo\
|
|
||||||
######\
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/######
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/###### ######
|
|
||||||
/o
|
|
||||||
/ooo
|
|
||||||
######/###### ###### ###### |}]
|
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@ let find (grid : 'a t) pred =
|
||||||
Some (vec2_of_idx ~width:grid.width ~idx, item)
|
Some (vec2_of_idx ~width:grid.width ~idx, item)
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
let count grid pred =
|
||||||
|
Array.fold (fun count item -> if pred item then count + 1 else count) 0 grid.items
|
||||||
|
;;
|
||||||
|
|
||||||
let init ~width ~height init =
|
let init ~width ~height init =
|
||||||
{ width
|
{ width
|
||||||
; height
|
; height
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ val ( .%()<- ) : 'a t -> Vec2.t -> 'a -> unit
|
||||||
val init : width:int -> height:int -> (Vec2.t -> 'a) -> 'a t
|
val init : width:int -> height:int -> (Vec2.t -> 'a) -> 'a t
|
||||||
val of_lines : (char -> 'a) -> string list -> 'a t
|
val of_lines : (char -> 'a) -> string list -> 'a t
|
||||||
val find : 'a t -> ('a -> bool) -> (Vec2.t * 'a) option
|
val find : 'a t -> ('a -> bool) -> (Vec2.t * 'a) option
|
||||||
|
val count : 'a t -> ('a -> bool) -> int
|
||||||
val iter_region : 'a t -> Vec2.t -> Vec2.t -> (Vec2.t -> unit) -> unit
|
val iter_region : 'a t -> Vec2.t -> Vec2.t -> (Vec2.t -> unit) -> unit
|
||||||
val iter : 'a t -> (Vec2.t -> unit) -> unit
|
val iter : 'a t -> (Vec2.t -> unit) -> unit
|
||||||
val draw : 'a t -> ('a -> char) -> string
|
val draw : 'a t -> ('a -> char) -> string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user