use std::time::{Duration, Instant}; fn between(field: &str, lower: i32, higher: i32) -> bool { let n: i32 = field.parse().unwrap(); n >= lower && n <= higher } pub fn run(print: bool) -> Duration { let input = std::fs::read_to_string("../inputs/04").unwrap(); let now = Instant::now(); let passports: Vec<_> = input .split("\n\n") .map(|p| p.replace('\n', " ").trim().to_string()) .collect(); let valid_passports = passports.iter().filter(|p| { p.contains("byr") && p.contains("iyr") && p.contains("eyr") && p.contains("hgt") && p.contains("hcl") && p.contains("ecl") && p.contains("pid") }); let mut part1 = 0; let part2 = valid_passports .filter(|p| { part1 += 1; let mut valid = true; for field in p.split(' ') { let mut parts = field.split(':'); let label = parts.next().unwrap(); let value = parts.next().unwrap(); valid = valid && match label { "byr" => between(value, 1920, 2002), "iyr" => between(value, 2010, 2020), "eyr" => between(value, 2020, 2030), "hgt" => { let height = &value[..value.len() - 2]; (value.ends_with("in") && between(height, 59, 76)) || (value.ends_with("cm") && between(height, 150, 193)) } "hcl" => value.starts_with("#"), "ecl" => { value == "amb" || value == "blu" || value == "brn" || value == "gry" || value == "grn" || value == "hzl" || value == "oth" } "pid" => value.len() == 9, "cid" => true, _ => false, } } valid }) .count(); let elapsed = now.elapsed(); if print { dbg!(elapsed, part1, part2); } elapsed }