type line = {first: int; second: int; char: char; pass: string} let parse_line str = Scanf.sscanf str "%d - %d %c : %s" (fun first second char pass -> {first; second; char; pass}) let count_str c str = let res = ref 0 in String.iter (fun d -> if c = d then incr res) str; !res let ok1 {first; second; char; pass} = let res = count_str char pass in res >= first && res <= second let ok2 {first; second; char; pass} = (pass.[first - 1] = char) <> (pass.[second - 1] = char) let main' ok input = let count_all = ref 0 in let count_ok = ref 0 in let check l = incr count_all; if ok l then incr count_ok in Bracket.infile_iter_lines input ~line:parse_line ~iter:check; Printf.printf "%d out of %d ok\n" !count_ok !count_all let mains = [|main' ok1; main' ok2|] let main = function | [part; input] -> mains.(int_of_string part - 1) input | _ -> Usage.exit "2 " let%expect_test "part 1" = mains.(0) "../../data/day2"; [%expect{| 607 out of 1000 ok |}] let%expect_test "part 2" = mains.(1) "../../data/day2"; [%expect{| 321 out of 1000 ok |}]