~turminal/aoc2020

9265a91892693a7b5fdc2256693a0226858c83a2 — Bor Grošelj Simić 3 years ago fedca4b
day 4

because parse not validate isn't a thing at all
1 files changed, 51 insertions(+), 0 deletions(-)

A day_4.ml
A day_4.ml => day_4.ml +51 -0
@@ 0,0 1,51 @@
open Printf
open Scanf

let rec rest_of_entry chan =
	match (try (input_line chan) with End_of_file -> "") with
	| "" -> ""
	| line -> line ^ " " ^ (rest_of_entry chan)

let valid_field fd_name contents =
	let in_range lb ub num = lb <= num && num <= ub in
	let eye_colors = [ "amb"; "blu"; "brn"; "gry"; "grn"; "hzl"; "oth" ] in
	try match (fd_name, contents) with
	| "byr", s -> sscanf s "%4d%!" (in_range 1920 2002)
	| "iyr", s -> sscanf s "%4d%!" (in_range 2010 2020)
	| "eyr", s -> sscanf s "%4d%!" (in_range 2020 2030)
	| "hgt", s -> sscanf s "%d%2s%!" (fun d s ->
			(in_range 150 193 d) && s = "cm" || (in_range 59 76 d) && s = "in")
	| "ecl", s -> List.mem s eye_colors
	| "hcl", s -> String.length s = 7 && sscanf s "#%_6x%!" true
	| "pid", s -> String.length s = 9 && sscanf s "%_9d%!" true
	| _ -> false
	with e -> false

let is_valid2 ent = List.for_all (fun e -> sscanf e "%[^:]:%s" valid_field) ent
let filter_cid ent = List.filter (fun f -> "cid:" <> String.sub f 0 4) ent

let rec read_from chan =
	let to_list str = List.filter ((<>) "") (String.split_on_char ' ' str) in
	match (try Some (input_line chan) with End_of_file -> None) with
	| Some line ->
			let entry_str = line ^ " " ^ (rest_of_entry chan) in
			(to_list entry_str) :: read_from chan
	| None -> []

let _ =
	let in_chan = open_in "day_4.in" in

	let lst = read_from in_chan in
	close_in in_chan;

	let nocid = lst |> List.map filter_cid in
	let valid1 = nocid |> List.filter (fun e -> List.length e = 7) in

	let out_chan1 = open_out "day_4_1.out" in
	valid1 |> List.length |> fprintf out_chan1 "%d\n";
	close_out out_chan1;

	let out_chan2 = open_out "day_4_2.out" in
	valid1 |> List.filter is_valid2 |> List.length |> fprintf out_chan2 "%d\n" ;
	close_out out_chan2;
	()