74 lines
2.5 KiB
OCaml
74 lines
2.5 KiB
OCaml
let read_file_rev name =
|
|
let ic = open_in name in
|
|
let try_read () =
|
|
try Some (input_line ic)
|
|
with End_of_file -> None in
|
|
let rec loop acc line =
|
|
match try_read () with
|
|
| Some "" -> loop ((String.trim line)::acc) ""
|
|
| Some s -> loop acc (String.concat " " [line; s])
|
|
| None -> close_in ic; (String.trim line)::acc in
|
|
loop [] ""
|
|
|
|
|
|
type passport =
|
|
{ byr: int (* Birth Year *)
|
|
; iyr: int (* Issue Year*)
|
|
; eyr: int (* Expiration Year *)
|
|
; hgt: string (* Height *)
|
|
; hcl: string (* Hair Color *)
|
|
; ecl: string (* Eye Color *)
|
|
; pid: string (* Passport ID *)
|
|
; cid: string option (* Country ID *)
|
|
}
|
|
|
|
let passport_of_string s =
|
|
let map = String.split_on_char ' ' s
|
|
|> List.map (String.split_on_char ':')
|
|
|> List.map (fun [k; v] -> (k, v)) in
|
|
try Some
|
|
{ byr = int_of_string (List.assoc "byr" map)
|
|
; iyr = int_of_string (List.assoc "iyr" map)
|
|
; eyr = int_of_string (List.assoc "eyr" map)
|
|
; hgt = List.assoc "hgt" map
|
|
; hcl = List.assoc "hcl" map
|
|
; ecl = List.assoc "ecl" map
|
|
; pid = List.assoc "pid" map
|
|
; cid = List.assoc_opt "cid" map
|
|
}
|
|
with Not_found -> None
|
|
|
|
|
|
let is_height_ok pspt =
|
|
try
|
|
let h = int_of_string (List.hd (String.split_on_char 'c' pspt.hgt)) in
|
|
h >= 150 && h <= 193
|
|
with _ ->
|
|
try
|
|
let h = int_of_string (List.hd (String.split_on_char 'i' pspt.hgt)) in
|
|
h >= 59 && h <= 76
|
|
with _ -> false
|
|
|
|
|
|
let part1 l =
|
|
List.filter_map passport_of_string l |> List.length
|
|
|
|
let part2 l =
|
|
List.filter_map passport_of_string l
|
|
|> List.filter (fun p -> p.byr >= 1920 && p.byr <= 2002
|
|
&& p.iyr >= 2010 && p.iyr <= 2020
|
|
&& p.eyr >= 2020 && p.eyr <= 2030
|
|
&& Str.string_match (Str.regexp {|^[0-9]+\(cm\|in\)$|}) p.hgt 0
|
|
&& is_height_ok p
|
|
&& Str.string_match (Str.regexp {|^#[0-9a-f]+$|}) p.hcl 0
|
|
&& String.length p.hcl = 7
|
|
&& List.mem p.ecl ["amb"; "blu"; "brn"; "gry"; "grn"; "hzl"; "oth"]
|
|
&& String.length p.pid = 9
|
|
&& Str.string_match (Str.regexp {|^[0-9]+$|}) p.pid 0)
|
|
|> List.length
|
|
|
|
|
|
let () =
|
|
print_endline (string_of_int (read_file_rev filename |> part1))
|
|
let () =
|
|
print_endline (string_of_int (read_file_rev filename |> part2))
|