day 2
This commit is contained in:
parent
512ae7d3d7
commit
816b2851c4
5 changed files with 1052 additions and 9 deletions
|
@ -1,4 +1,4 @@
|
|||
let days = [|Day1.main|]
|
||||
let days = [|Day1.main; Day2.main|]
|
||||
|
||||
let _ =
|
||||
match Array.to_list Sys.argv with
|
||||
|
|
13
bracket.ml
13
bracket.ml
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
41
day2.ml
Normal file
41
day2.ml
Normal 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>"
|
Loading…
Reference in a new issue