use std::error::Error; use std::fs; use std::collections::HashMap; use std::str; use regex::Regex; pub fn both(filename: &str) -> Result<(), Box> { let contents = fs::read_to_string(filename)?; let mut valid_passports_simple = 0; let mut valid_passports_extra = 0; let mut passport: HashMap<&str, &str> = HashMap::new(); for line in contents.lines() { if line.trim() == "" { if passport.len() == 8 || (passport.len() == 7 && !passport.contains_key("cid")) { valid_passports_simple += 1; if validate_passport(passport) { valid_passports_extra += 1; } } passport = HashMap::new(); continue } let entries = line.split(" "); for entry in entries { let kv: Vec<&str> = entry.split(":").collect(); passport.insert(kv[0], kv[1]); } } println!("Valid Passports: {}", valid_passports_simple); println!("Extra Valid Passports: {}", valid_passports_extra); Ok(()) } fn validate_passport(passport: HashMap<&str, &str>) -> bool { let byr: u32 = passport.get("byr").unwrap().parse().unwrap(); if byr < 1920 || byr > 2002 { return false } let iyr: u32 = passport.get("iyr").unwrap().parse().unwrap(); if iyr < 2010 || iyr > 2020 { return false } let eyr: u32 = passport.get("eyr").unwrap().parse().unwrap(); if eyr < 2020 || eyr > 2030 { return false } let hgt = passport.get("hgt").unwrap(); if hgt.ends_with("cm") { let hval: u32 = hgt.split("cm").nth(0).unwrap().parse().unwrap(); if hval < 150 || hval > 193 { return false } } else if hgt.ends_with("in") { let hval: u32 = hgt.split("in").nth(0).unwrap().parse().unwrap(); if hval < 59 || hval > 76 { return false } } else { return false } let hcl = passport.get("hcl").unwrap(); let hcl_re = Regex::new(r"\#[0-9a-f]{6}").unwrap(); if !hcl_re.is_match(hcl) { return false } let ecl = passport.get("ecl").unwrap().trim(); if ecl.len() != 3 || !"amb blu brn gry grn hzl oth".contains(ecl) { return false } let pid = passport.get("pid").unwrap(); let pid_re = Regex::new(r"^[0-9]{9}$").unwrap(); if !pid_re.is_match(pid) { return false } true }