Mercurial > lbo > hg > aoc22
view 2023/day09.ml @ 55:3aa1f3d5ee56
Day 09 Part 1
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Fri, 15 Dec 2023 11:03:13 +0100 |
parents | |
children | 3175a3fe84e5 |
line wrap: on
line source
open Base open Core open Angstrom type seq = int list [@@deriving sexp] module Parse = struct let maybe p = option () (p >>= fun _ -> return ()) let intP = take_while1 (fun c -> Char.(c = '-' || is_digit c)) >>| Int.of_string let int_listP = skip_many (char ' ') *> sep_by1 (skip_many1 (char ' ')) intP let int_listsP = sep_by1 (char '\n') int_listP <* maybe (char '\n') exception Parse_exn of string let parse_input ch : seq list = let inp = In_channel.input_all ch in match parse_string ~consume:All int_listsP inp with | Ok ok -> ok | Error e -> raise (Parse_exn e) end module Part1 = struct let reduce1 s = let f (a, last) e = ((e - last) :: a, e) in match s with | [] -> assert false | [ _ ] -> assert false | x :: xs -> List.fold ~init:([], x) ~f xs let rec all_zeros = function | 0 :: rest -> all_zeros rest | _ :: _ -> false | [] -> true let rec reduce_all s = let last = List.last_exn s in let reduced, _ = reduce1 s in if all_zeros reduced then last else let next = reduce_all (List.rev reduced) in Out_channel.printf "%d / %d\n" next last; next + last let process = List.map ~f:reduce_all end let () = let inp = Parse.parse_input In_channel.stdin in let result = Part1.process inp in let str = Sexp.to_string_hum @@ sexp_of_seq result in Out_channel.( output_string stdout str; output_string stdout "\n"; printf "Result: %d\n" (List.fold ~init:0 ~f:Int.( + ) result))