Compare commits

..

4 Commits

Author SHA1 Message Date
aaa031e6c6 Move memoize to the Aoc library. 2024-12-19 11:53:59 +00:00
4f963e0f98 Tidy up 2024 day 19 2024-12-19 11:31:44 +00:00
4c9ae83184 2024 day 19 part 2. 2024-12-19 11:10:16 +00:00
33d7b34002 2024 day 19 part 1 2024-12-19 11:06:02 +00:00
4 changed files with 62 additions and 2 deletions

45
bin/day2419.ml Normal file
View File

@@ -0,0 +1,45 @@
(** [towels_of_strings lst] returns a pair containing a list of available towels
and a list of patterns wanted. *)
let towels_of_strings = function
| h :: "" :: t ->
let re = Str.regexp "[, ]+" in
let h = Str.split re h in
(h, t)
| _ -> failwith "towels_of_strings"
(** [towels_of_file fname] returns the list of towels and patterns from the file
[fname]. *)
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
(** [count_hashes memo towels pattern] counts the number of ways of matching
[pattern] using [towels]. [memo] is a hashtable used for memoizing results.
*)
let rec count_matches memo towels pattern =
let pattern_len = String.length pattern in
let rec count_matched = function
| [] -> 0
| h :: t ->
let towel_len = String.length h in
if String.starts_with ~prefix:h pattern then
Aoc.memoize memo
(count_matches memo towels)
(String.sub pattern towel_len (pattern_len - towel_len))
+ count_matched t
else count_matched t
in
if pattern_len = 0 then 1 else count_matched towels
let part1 (towels, patterns) =
List.map (Aoc.memoize memo (count_matches memo towels)) patterns
|> List.filter (( < ) 0)
|> List.length
let part2 (towels, patterns) =
List.map (Aoc.memoize memo (count_matches memo towels)) patterns
|> List.fold_left ( + ) 0
let _ =
Aoc.main towels_of_file [ (string_of_int, part1); (string_of_int, part2) ]

View File

@@ -17,7 +17,8 @@
day2415 day2415
day2416 day2416
day2417 day2417
day2418) day2418
day2419)
(names (names
day2401 day2401
day2402 day2402
@@ -36,5 +37,6 @@
day2415 day2415
day2416 day2416
day2417 day2417
day2418) day2418
day2419)
(libraries str aoc)) (libraries str aoc))

View File

@@ -90,3 +90,11 @@ let pow10 n =
let rec impl acc = function 0 -> acc | x -> impl (acc * 10) (x - 1) in let rec impl acc = function 0 -> acc | x -> impl (acc * 10) (x - 1) in
assert (n >= 0); assert (n >= 0);
impl 1 n 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

View File

@@ -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 [string_of_int]). The second executes the given part. Output is given as if
done by: [print_string ( prep fname |> snd |> fst )] *) 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 representing a pair of integers, useful for Set.Make *)
module IntPair : sig module IntPair : sig
type t = int * int type t = int * int