From aaa031e6c6e676eaa7a69e78a2cf7c75686cb9e7 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 19 Dec 2024 11:53:59 +0000 Subject: [PATCH] Move memoize to the Aoc library. --- bin/day2419.ml | 19 ++++--------------- lib/aoc.ml | 8 ++++++++ lib/aoc.mli | 5 +++++ 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/bin/day2419.ml b/bin/day2419.ml index 543d520..5b7f00f 100644 --- a/bin/day2419.ml +++ b/bin/day2419.ml @@ -14,17 +14,6 @@ let towels_of_file fname = Aoc.strings_of_file fname |> towels_of_strings (** Memoizing hash table shared between parts 1 and 2. *) let memo = Hashtbl.create 1000 -(** [memoize memo f value] returns the result of [f value]. The hashtable [memo] - is used to cache results, so repeated calls with the same [value] will not - call [f] again. *) -let memoize memo f value = - match Hashtbl.find_opt memo value with - | Some x -> x - | None -> - let x = f value in - Hashtbl.add memo value x; - x - (** [count_hashes memo towels pattern] counts the number of ways of matching [pattern] using [towels]. [memo] is a hashtable used for memoizing results. *) @@ -35,7 +24,7 @@ let rec count_matches memo towels pattern = | h :: t -> let towel_len = String.length h in if String.starts_with ~prefix:h pattern then - memoize memo + Aoc.memoize memo (count_matches memo towels) (String.sub pattern towel_len (pattern_len - towel_len)) + count_matched t @@ -44,12 +33,12 @@ let rec count_matches memo towels pattern = if pattern_len = 0 then 1 else count_matched towels let part1 (towels, patterns) = - List.map (count_matches memo towels) patterns - |> List.filter (( > ) 0) + List.map (Aoc.memoize memo (count_matches memo towels)) patterns + |> List.filter (( < ) 0) |> List.length let part2 (towels, patterns) = - List.map (memoize memo (count_matches memo towels)) patterns + List.map (Aoc.memoize memo (count_matches memo towels)) patterns |> List.fold_left ( + ) 0 let _ = diff --git a/lib/aoc.ml b/lib/aoc.ml index 02dddd1..62a3885 100644 --- a/lib/aoc.ml +++ b/lib/aoc.ml @@ -90,3 +90,11 @@ let pow10 n = let rec impl acc = function 0 -> acc | x -> impl (acc * 10) (x - 1) in assert (n >= 0); impl 1 n + +let memoize memo f value = + match Hashtbl.find_opt memo value with + | Some x -> x + | None -> + let x = f value in + Hashtbl.add memo value x; + x diff --git a/lib/aoc.mli b/lib/aoc.mli index c99630c..aa194ee 100644 --- a/lib/aoc.mli +++ b/lib/aoc.mli @@ -30,6 +30,11 @@ val main : (string -> 'a) -> (('b -> string) * ('a -> 'b)) list -> unit [string_of_int]). The second executes the given part. Output is given as if done by: [print_string ( prep fname |> snd |> fst )] *) +val memoize : ('a, 'b) Hashtbl.t -> ('a -> 'b) -> 'a -> 'b +(** [memoize memo f value] returns the result of [f value]. The hashtable [memo] + is used to cache results, so repeated calls with the same [value] will not + call [f] again. *) + (** Module representing a pair of integers, useful for Set.Make *) module IntPair : sig type t = int * int