2020/rust/src/day04.rs

75 lines
2.3 KiB
Rust

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
}