Mercurial > lbo > hg > aoc22
view 2023/day06.ml @ 51:fd579cbd3a93
Leakyroof: add a few comments
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Wed, 13 Dec 2023 15:02:07 +0100 |
parents | 070e01565b16 |
children |
line wrap: on
line source
open Angstrom open Base open Core type race = { time : int; distance : int } [@@deriving sexp] module Parse = struct let maybe p = option () (p >>= fun _ -> return ()) let intP = take_while1 (function '0' .. '9' -> true | _ -> false) >>| Int.of_string let int_listP = skip_many (char ' ') *> sep_by1 (skip_while Char.is_whitespace) intP let timesP = string "Time:" *> skip_while Char.is_whitespace *> int_listP <* char '\n' let distancesP = string "Distance:" *> skip_while Char.is_whitespace *> int_listP <* maybe (char '\n') exception Parse_exn of string let parse_input ch = let input = In_channel.input_all ch in match parse_string ~consume:All (list [ timesP; distancesP ]) input with | Ok (a :: b :: _) -> let zipped = List.zip_exn a b in List.map ~f:(fun (time, distance) -> { time; distance }) zipped | Ok _ -> raise (Parse_exn "not enough parts") | Error e -> raise (Parse_exn e) end module Part1 = struct (* we only need to calculate the two roots of the quadratic equation 0 = t_hold ** 2 - t_race * t_hold + distance / acceleration where acceleration is 1 mm/ms**2. The number of integers between roots is the solution. *) let hold_times t0 x0 = let open Float in let p_half = -.t0 /. 2. in let q = x0 in let min = -.p_half -. sqrt ((p_half ** 2.) -. q) in let max = -.p_half +. sqrt ((p_half ** 2.) -. q) in (min, max -. 1e-6) let possibilities t0 x0 = let min, max = hold_times (Float.of_int t0) (Float.of_int x0) in Out_channel.printf "%f %f\n" min max; let diff = Int.of_float (Float.round_down min) - Int.of_float (Float.round_down max) in Int.abs diff let process races = let f { time; distance } = possibilities time distance in let all_possibs = List.map ~f races in Out_channel.print_endline (Sexp.to_string_hum (List.sexp_of_t Int.sexp_of_t all_possibs)); List.fold ~init:1 ~f:( * ) all_possibs end let () = let parsed = Parse.parse_input In_channel.stdin in Out_channel.printf "%d\n" (Part1.process parsed)