let ints_of_string ?(sep = " ") s = List.map int_of_string (Str.split (Str.regexp sep) s) let distance1 a b = abs (a - b) let strings_of_file fname = In_channel.with_open_text fname In_channel.input_lines let main prep parts = try match Sys.argv with | [| _; fname |] -> let lines = prep fname in let do_part i (fmt, fn) = Printf.printf "Part %d = %s\n" (i + 1) (fmt (fn lines)); flush stdout in List.iteri do_part parts; exit 0 | _ -> Printf.printf "Usage: %s \n" Sys.executable_name; exit 2 with e -> Printf.fprintf stderr "An error occured: %s\n" (Printexc.to_string e); if Printexc.backtrace_status () then ( Printf.fprintf stderr "Backtrace:\n"; Printexc.print_backtrace stderr); exit 1 module IntPair = struct type t = int * int let compare (x, y) (x', y') = match compare y y' with 0 -> compare x x' | c -> c end module IntPairSet = Set.Make (IntPair) module Grid = struct type t = { grid : string; width : int; height : int } let of_file fname = let strs = strings_of_file fname in let width = String.length (List.hd strs) in let grid = List.fold_left ( ^ ) "" strs in let height = String.length grid / width in { grid; width; height } let length grid = String.length grid.grid let pos_of_idx grid idx = (idx mod grid.width, idx / grid.width) let idx_of_pos grid (x, y) = x + (y * grid.width) let get_by_idx grid idx = grid.grid.[idx] let get_by_pos grid pos = get_by_idx grid (idx_of_pos grid pos) let pos_is_valid grid (x, y) = x >= 0 && x < grid.width && y >= 0 && y < grid.height let idx_from_opt grid = String.index_from_opt grid.grid let update_pos grid pos c = let idx = idx_of_pos grid pos in let builder = Buffer.create (length grid) in Buffer.add_string builder (String.sub grid.grid 0 idx); Buffer.add_char builder c; Buffer.add_string builder (String.sub grid.grid (idx + 1) (length grid - idx - 1)); { grid with grid = Buffer.contents builder } end let log10i i = let rec impl acc = function 0 -> acc | x -> impl (acc + 1) (x / 10) in assert (i > 0); impl ~-1 i let digits10 = function | 0 -> 1 | n when n > 0 -> 1 + log10i n | n (* when n < 0 *) -> 1 + log10i (-n) let pow10 n = let rec impl acc = function 0 -> acc | x -> impl (acc * 10) (x - 1) in assert (n >= 0); impl 1 n