diff --git a/bin/day2406.ml b/bin/day2406.ml index d4ae9a2..049d962 100644 --- a/bin/day2406.ml +++ b/bin/day2406.ml @@ -1,16 +1,4 @@ -(** [IntPair] is a module describing pairs of ints, suitable for using with - [Set.Make]. *) -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 PosSet = Set.Make (IntPair) -(** [PosSet] represents a set of positions. *) - -type map = { blocks : PosSet.t; width : int; height : int } +type map = { blocks : Aoc.IntPairSet.t; width : int; height : int } (** [map] represents a map with [blocks] and a [width] and [height]. *) (** [find_start strs] returns the location [(x, y)] of the starting position. *) @@ -29,14 +17,14 @@ let find_start strs = let map_of_strings strs = let rec row_scan acc y pos s = match String.index_from_opt s pos '#' with - | Some x -> row_scan (PosSet.add (x, y) acc) y (x + 1) s + | Some x -> row_scan (Aoc.IntPairSet.add (x, y) acc) y (x + 1) s | None -> acc in let rec impl acc y = function | h :: t -> impl (row_scan acc y 0 h) (y + 1) t | [] -> (acc, y) in - let blocks, height = impl PosSet.empty 0 strs in + let blocks, height = impl Aoc.IntPairSet.empty 0 strs in let width = String.length (List.hd strs) in { blocks; height; width } @@ -62,7 +50,7 @@ let is_valid_pos map (x, y) = the updated [(pos, vel)] pair. *) let rec move map ((x, y), (dx, dy)) = let x', y' = (x + dx, y + dy) in - if PosSet.mem (x', y') map.blocks then move map ((x, y), (-dy, dx)) + if Aoc.IntPairSet.mem (x', y') map.blocks then move map ((x, y), (-dy, dx)) else ((x', y'), (dx, dy)) (** [walk_map map (pos, vel)] walks around [map] starting at [pos] moving in the @@ -97,15 +85,15 @@ let has_cycles map (pos, vel) = let walk_block map (pos, vel) bpos = if bpos = pos then false else - let map' = { map with blocks = PosSet.add bpos map.blocks } in + let map' = { map with blocks = Aoc.IntPairSet.add bpos map.blocks } in has_cycles map' (pos, vel) let part1 (map, pos, vel) = - walk_map map (pos, vel) |> List.sort_uniq IntPair.compare |> List.length + walk_map map (pos, vel) |> List.sort_uniq Aoc.IntPair.compare |> List.length let part2 (map, pos, vel) = walk_map map (pos, vel) - |> List.sort_uniq IntPair.compare + |> List.sort_uniq Aoc.IntPair.compare |> List.filter (walk_block map (pos, vel)) |> List.length diff --git a/lib/aoc.ml b/lib/aoc.ml index 406d331..5082485 100644 --- a/lib/aoc.ml +++ b/lib/aoc.ml @@ -23,3 +23,12 @@ let main prep parts = with e -> Printf.printf "An error occured: %s\n" (Printexc.to_string e); 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) diff --git a/lib/aoc.mli b/lib/aoc.mli index 3acc871..409184e 100644 --- a/lib/aoc.mli +++ b/lib/aoc.mli @@ -15,3 +15,62 @@ val main : (string -> 'a) -> (('b -> string) * ('a -> 'b)) list -> unit pair of functions. The first converts the output to a string (for example [string_of_int]). The second executes the given part. Output is given as if done by: [print_string ( prep fname |> snd |> fst )] *) + +(** Module representing a pair of integers, useful for Set.Make *) +module IntPair : sig + type t = int * int + (** [t] is a pair of integers *) + + val compare : t -> t -> int + (** Standard comparion operation. *) +end + +(** IntPairSet represents a Set of integers, see standard docs for info. *) +module IntPairSet : sig + type elt = IntPair.t + type t = Set.Make(IntPair).t + + val empty : t + val add : elt -> t -> t + val singleton : elt -> t + val remove : elt -> t -> t + val union : t -> t -> t + val inter : t -> t -> t + val disjoint : t -> t -> bool + val diff : t -> t -> t + val cardinal : t -> int + val elements : t -> elt list + val min_elt : t -> elt + val min_elt_opt : t -> elt option + val max_elt : t -> elt + val max_elt_opt : t -> elt option + val choose : t -> elt + val choose_opt : t -> elt option + val find : elt -> t -> elt + val find_opt : elt -> t -> elt option + val find_first : (elt -> bool) -> t -> elt + val find_first_opt : (elt -> bool) -> t -> elt option + val find_last : (elt -> bool) -> t -> elt + val find_last_opt : (elt -> bool) -> t -> elt option + val iter : (elt -> unit) -> t -> unit + val fold : (elt -> 'acc -> 'acc) -> t -> 'acc -> 'acc + val map : (elt -> elt) -> t -> t + val filter : (elt -> bool) -> t -> t + val filter_map : (elt -> elt option) -> t -> t + val partition : (elt -> bool) -> t -> t * t + val split : elt -> t -> t * bool * t + val is_empty : t -> bool + val mem : elt -> t -> bool + val equal : t -> t -> bool + val compare : t -> t -> int + val subset : t -> t -> bool + val for_all : (elt -> bool) -> t -> bool + val exists : (elt -> bool) -> t -> bool + val to_list : t -> elt list + val of_list : elt list -> t + val to_seq_from : elt -> t -> elt Seq.t + val to_seq : t -> elt Seq.t + val to_rev_seq : t -> elt Seq.t + val add_seq : elt Seq.t -> t -> t + val of_seq : elt Seq.t -> t +end