Mercurial > lbo > hg > aoc22
view 2023/day04.ml @ 41:d4baa11fdac8
Day 04 Part 1
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Mon, 04 Dec 2023 22:31:00 +0100 |
parents | |
children | 95af5cf548c5 |
line wrap: on
line source
open Angstrom open Base open Core module Hashtbl = Base.Hashtbl type card = { id : int; winning : int list; have : int list } [@@deriving sexp] module Parse = struct (* Parse cards such as Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 *) let intP = take_while1 (function '0' .. '9' -> true | _ -> false) >>| Int.of_string let int_listP = skip_many (char ' ') *> sep_by1 (skip_many1 (char ' ')) intP let card_headP = (string "Card" *> skip_many1 (char ' ')) *> intP <* string ": " let sepP = string " | " let card = let open Angstrom.Let_syntax in let%bind id = card_headP in let%bind winning = int_listP in let%bind _ = sepP in let%bind have = int_listP in return { id; winning; have } exception ParseExn of string let parse_card line = match parse_string ~consume:All card line with | Ok card -> card | Error e -> raise (ParseExn e) end module Part1 = struct let to_set ilist = Set.of_list (module Int : Comparator.S with type t = Int.t and type comparator_witness = Int.comparator_witness) ilist let list_intersect a b = let sa = to_set a in let sb = to_set b in Set.inter sa sb let card_value c = Int.pow 2 (Set.length (list_intersect c.winning c.have)) / 2 let _test_parse ch = let process l = let card = Parse.parse_card l in let sexp = Sexp.to_string_hum (sexp_of_card (Parse.parse_card l)) in let value = card_value card in Printf.sprintf "%s - value: %d" sexp value in let f l = Out_channel.print_endline (process l) in In_channel.iter_lines ch ~f let solve ch = let f acc line = let card = Parse.parse_card line in acc + card_value card in let result = In_channel.fold_lines ch ~init:0 ~f in Out_channel.printf "Total value is %d\n" result end let () = Part1.solve In_channel.stdin