2024 day 15 part 2
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
type grid = { grid : char array; width : int; height : int }
|
||||
|
||||
let grid_make strs =
|
||||
let grid_make posmap_fn strs =
|
||||
let grid =
|
||||
List.fold_left String.cat "" strs |> String.to_seq |> Array.of_seq
|
||||
List.fold_left String.cat "" strs
|
||||
|> posmap_fn |> String.to_seq |> Array.of_seq
|
||||
in
|
||||
let height = List.length strs in
|
||||
let width = Array.length grid / height in
|
||||
Printf.printf "width %d height %d \n" width height;
|
||||
{ grid; width; height }
|
||||
|
||||
let grid_copy grid = { grid with grid = Array.copy grid.grid }
|
||||
let grid_height grid = grid.height
|
||||
let[@warning "-32"] grid_length grid = grid.width * grid.height
|
||||
|
||||
let[@warning "-32"] grid_print grid =
|
||||
Array.iteri
|
||||
(fun i c ->
|
||||
@@ -32,28 +30,62 @@ let instrs_of_file fname =
|
||||
| h :: t -> impl (h :: acc) t
|
||||
in
|
||||
let grid, moves = impl [] strs in
|
||||
let grid = grid_make grid in
|
||||
( grid,
|
||||
List.fold_left String.cat "" moves |> String.to_seq |> List.of_seq,
|
||||
find_start_idx grid )
|
||||
(grid, List.fold_left String.cat "" moves |> String.to_seq |> List.of_seq)
|
||||
|
||||
let rec move_robot grid i di =
|
||||
let rec move_robot_x grid i di =
|
||||
match grid.grid.(i + di) with
|
||||
| '#' -> i
|
||||
| 'O' ->
|
||||
if move_robot grid (i + di) di = i + di then i else move_robot grid i di
|
||||
| 'O' | '[' | ']' ->
|
||||
if move_robot_x grid (i + di) di = i + di then i
|
||||
else move_robot_x grid i di
|
||||
| '.' ->
|
||||
grid.grid.(i + di) <- grid.grid.(i);
|
||||
grid.grid.(i) <- '.';
|
||||
i + di
|
||||
| _ -> failwith "move_robot"
|
||||
| _ -> failwith "move_robot_x"
|
||||
|
||||
let rec can_move_y grid i di =
|
||||
match grid.grid.(i + di) with
|
||||
| '#' -> false
|
||||
| '.' -> true
|
||||
| 'O' -> can_move_y grid (i + di) di
|
||||
| '[' -> can_move_y grid (i + di) di && can_move_y grid (i + di + 1) di
|
||||
| ']' -> can_move_y grid (i + di - 1) di && can_move_y grid (i + di) di
|
||||
| _ -> failwith "can_move_y"
|
||||
|
||||
let move_robot_y grid i di =
|
||||
let rec do_move i =
|
||||
match grid.grid.(i + di) with
|
||||
| '#' -> failwith "move_robot_y.do_move #"
|
||||
| '.' ->
|
||||
grid.grid.(i + di) <- grid.grid.(i);
|
||||
grid.grid.(i) <- '.'
|
||||
| 'O' ->
|
||||
do_move (i + di);
|
||||
do_move i
|
||||
| '[' ->
|
||||
do_move (i + di);
|
||||
do_move (i + di + 1);
|
||||
do_move i
|
||||
| ']' ->
|
||||
do_move (i + di - 1);
|
||||
do_move (i + di);
|
||||
do_move i
|
||||
| _ -> failwith "move_robot_y.do_move"
|
||||
in
|
||||
if can_move_y grid i di then (
|
||||
do_move i;
|
||||
i + di)
|
||||
else i
|
||||
|
||||
let process_move grid robot dir =
|
||||
(*grid_print grid;
|
||||
Printf.printf "\nMove: %c\n" dir;*)
|
||||
match dir with
|
||||
| '^' -> move_robot grid robot ~-(grid_height grid)
|
||||
| 'v' -> move_robot grid robot (grid_height grid)
|
||||
| '<' -> move_robot grid robot ~-1
|
||||
| '>' -> move_robot grid robot 1
|
||||
| '^' -> move_robot_y grid robot ~-(grid.width)
|
||||
| 'v' -> move_robot_y grid robot grid.width
|
||||
| '<' -> move_robot_x grid robot ~-1
|
||||
| '>' -> move_robot_x grid robot 1
|
||||
| _ -> failwith "process_move"
|
||||
|
||||
let rec process_moves grid robot = function
|
||||
@@ -63,13 +95,31 @@ let rec process_moves grid robot = function
|
||||
let calc_score grid =
|
||||
Array.mapi
|
||||
(fun idx c ->
|
||||
if c = 'O' then (idx mod grid.width) + (100 * (idx / grid.height)) else 0)
|
||||
if c = 'O' || c = '[' then
|
||||
(idx mod grid.width) + (100 * (idx / grid.width))
|
||||
else 0)
|
||||
grid.grid
|
||||
|> Array.fold_left ( + ) 0
|
||||
|
||||
let part (grid, moves, robot) =
|
||||
let grid = grid_copy grid in
|
||||
let expand_grid str =
|
||||
let b = Buffer.create (String.length str * 2) in
|
||||
let add_c = function
|
||||
| '#' -> Buffer.add_string b "##"
|
||||
| 'O' -> Buffer.add_string b "[]"
|
||||
| '.' -> Buffer.add_string b ".."
|
||||
| '@' -> Buffer.add_string b "@."
|
||||
| _ -> failwith "expand_grid"
|
||||
in
|
||||
String.iter add_c str;
|
||||
Buffer.contents b
|
||||
|
||||
let part posmap_fn (grid, moves) =
|
||||
let grid = grid_make posmap_fn grid in
|
||||
let robot = find_start_idx grid in
|
||||
let _ = process_moves grid robot moves in
|
||||
(*grid_print grid;*)
|
||||
calc_score grid
|
||||
|
||||
let _ = Aoc.main instrs_of_file [ (string_of_int, part) ]
|
||||
let _ =
|
||||
Aoc.main instrs_of_file
|
||||
[ (string_of_int, part Fun.id); (string_of_int, part expand_grid) ]
|
||||
|
Reference in New Issue
Block a user