let pos_of_numeric_grid c = match c with | '7' -> (0, 0) | '8' -> (1, 0) | '9' -> (2, 0) | '4' -> (0, 1) | '5' -> (1, 1) | '6' -> (2, 1) | '1' -> (0, 2) | '2' -> (1, 2) | '3' -> (2, 2) | '0' -> (1, 3) | 'A' -> (2, 3) | _ -> raise (invalid_arg "pos_of_numeric_grid") let pos_of_dir_grid c = match c with | '^' -> (1, 3) | 'A' -> (2, 3) | '<' -> (0, 4) | 'v' -> (1, 4) | '>' -> (2, 4) | _ -> raise (invalid_arg "pos_of_dir_grid") let invalid_x, invalid_y = (0, 3) let rec move pos_of_grid builder (cx, cy) code = match Seq.uncons code with | None -> Buffer.contents builder | Some (c, t) -> let dx, dy = pos_of_grid c in if dx > cx && (cy = dy || cy <> invalid_y) then begin Buffer.add_string builder (String.make (dx - cx) '>'); move pos_of_grid builder (dx, cy) code end else if dx < cx && (cy = dy || cy <> invalid_y) then begin Buffer.add_string builder (String.make (cx - dx) '<'); move pos_of_grid builder (dx, cy) code end else if dy > cy && (cx = dx || cx <> invalid_x) then begin Buffer.add_string builder (String.make (dy - cy) 'v'); move pos_of_grid builder (cx, dy) code end else if dy < cy && (cx = dx || cx <> invalid_x) then begin Buffer.add_string builder (String.make (cy - dy) '^'); move pos_of_grid builder (cx, dy) code end else begin assert (cx = dx); assert (dy = dy); Buffer.add_char builder 'A'; move pos_of_grid builder (cx, cy) t end let process_code pos_of_grid code = let builder = Buffer.create 30 in move pos_of_grid builder (pos_of_grid 'A') (String.to_seq code) let human_insns code = let first_robot_insns = process_code pos_of_numeric_grid code in let second_robot_insns = process_code pos_of_dir_grid first_robot_insns in let human = process_code pos_of_dir_grid second_robot_insns in print_endline human; print_endline second_robot_insns; print_endline first_robot_insns; print_endline code; human let complexity code = let insns = human_insns code in let num = int_of_string (String.sub code 0 (String.length code - 1)) in Printf.printf "%s (%d): %s (%d) (%d) \n" code num insns (String.length insns) (num * String.length insns); num * String.length insns let part1 codes = List.map complexity codes |> List.fold_left ( + ) 0 let _ = Aoc.main Aoc.strings_of_file [ (string_of_int, part1) ] (* 175386 too high *)