This commit is contained in:
Rhiannon Morris 2020-12-02 12:05:38 +01:00
parent 512ae7d3d7
commit 816b2851c4
5 changed files with 1052 additions and 9 deletions

View File

@ -1,4 +1,4 @@
let days = [|Day1.main|]
let days = [|Day1.main; Day2.main|]
let _ =
match Array.to_list Sys.argv with

View File

@ -1,17 +1,16 @@
let bracket ~make ~act ~free =
let x = make () in
let bracket ~make:(lazy x) ~act ~free =
match act x with
| result -> free x; result
| exception e -> free x; raise e
let infile ~act name =
bracket ~make:(fun () -> open_in name) ~act ~free:close_in_noerr
bracket ~make:(lazy (open_in name)) ~act ~free:close_in_noerr
let infile_lines ~line:f ~of_seq name =
let get_line file =
match input_line file with
| exception End_of_file -> None
| line -> Some (f line, file)
in
try Some (f (input_line file), file)
with End_of_file -> None in
let act file = of_seq (Seq.unfold get_line file) in
infile name ~act
let infile_iter_lines ~line ~iter = infile_lines ~of_seq:(Seq.iter iter) ~line

View File

@ -1,5 +1,8 @@
val bracket: make:(unit -> 'a) -> act:('a -> 'b) -> free:('a -> unit) -> 'b
val bracket: make:('a Lazy.t) -> act:('a -> 'b) -> free:('a -> unit) -> 'b
val infile: act:(in_channel -> 'b) -> string -> 'b
val infile_lines: line:(string -> 'a) -> of_seq:('a Seq.t -> 'b) -> string -> 'b
val infile_iter_lines:
line:(string -> 'a) -> iter:('a -> unit) -> string -> unit

1000
data/day2 Normal file

File diff suppressed because it is too large Load Diff

41
day2.ml Normal file
View File

@ -0,0 +1,41 @@
let parse_line' f str = Scanf.sscanf str "%d - %d %c : %s%!" f
type part1 = {min: int; max: int; char: char; pass: string}
let parse_line1 = parse_line'
(fun min max char pass -> {min; max; char; pass})
let count c str =
let res = ref 0 in
String.iter (fun d -> if c = d then incr res) str;
!res
let ok1 {min; max; char; pass} =
let res = count char pass in
res >= min && res <= max
type part2 = {pos1: int; pos2: int; char: char; pass: string}
let parse_line2 = parse_line'
(fun pos1 pos2 char pass -> {pos1 = pos1 - 1; pos2 = pos2 - 1; char; pass})
let ok2 {pos1; pos2; char; pass} =
(pass.[pos1] = char) <> (pass.[pos2] = char)
let main' ~line ~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 ~iter:check;
Printf.printf "%d out of %d ok\n" !count_ok !count_all
let main1 = main' ~line:parse_line1 ~ok:ok1
let main2 = main' ~line:parse_line2 ~ok:ok2
let mains = [|main1; main2|]
let main = function
| [part; input] -> mains.(int_of_string part - 1) input
| _ -> Usage.exit "2 <part> <infile>"