Files
ocaml-aoc/lib/aoc.ml
Matthew Gretton-Dann 932b2c926c Tidy up code for 2024 day 12.
This still has some mutable state.
2024-12-12 10:23:08 +00:00

93 lines
2.6 KiB
OCaml

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 string_of_file fname =
match In_channel.with_open_text fname In_channel.input_line with
| Some x -> x
| None -> failwith "Aoc.string_of_file"
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 <fname>\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 pos_is_valid grid (x, y) =
x >= 0 && x < grid.width && y >= 0 && y < grid.height
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 get_by_pos_opt grid pos =
if pos_is_valid grid pos then Some (get_by_pos grid pos) else None
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