diff --git a/bin/day2415.ml b/bin/day2415.ml index 98fe22c..826cc5f 100644 --- a/bin/day2415.ml +++ b/bin/day2415.ml @@ -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) ]