mod common; use std::env; use common::{read_file, Passport, Result}; fn check_valid(passports: Vec) -> Result { let mut num_valid = 0; for passport in passports { let mut valid = passport.len() == 8 || (passport.len() == 7 && !passport.contains_key("cid")); if !valid { continue; }; let birth_year = passport.get("byr").unwrap(); valid = valid && birth_year.matches(|c: char| c.is_digit(10)).count() == 4 && (1920..=2002_u32).contains(&birth_year.parse()?); let issue_year = passport.get("iyr").unwrap(); valid = valid && issue_year.matches(|c: char| c.is_digit(10)).count() == 4 && (2010..=2020_u32).contains(&issue_year.parse()?); let expir_year = passport.get("eyr").unwrap(); valid = valid && expir_year.matches(|c: char| c.is_digit(10)).count() == 4 && (2020..=2030_u32).contains(&expir_year.parse()?); let height = passport.get("hgt").unwrap(); let height_cm = height.strip_suffix("cm").map(|h| h.parse().unwrap()); let height_in = height.strip_suffix("in").map(|h| h.parse().unwrap()); valid = valid && (height_cm.map(|h| (150..=193_u32).contains(&h)) == Some(true) || height_in.map(|h| (59..=76_u32).contains(&h)) == Some(true)); let hair_color = passport.get("hcl").unwrap().strip_prefix("#"); valid = valid && hair_color.is_some() && hair_color .unwrap() .matches(|c: char| c.is_digit(16)) .count() == 6; let eye_color = passport.get("ecl").unwrap(); valid = valid && ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"].contains(&eye_color.as_str()); let pass_id = passport.get("pid").unwrap(); valid = valid && pass_id.matches(|c: char| c.is_digit(10)).count() == 9; if valid { num_valid += 1; } } Ok(num_valid) } fn main() -> Result<()> { let path = env::args().skip(1).next().unwrap(); let passports = read_file(path)?; let num_valid = check_valid(passports)?; println!("{}", num_valid); Ok(()) }