75 lines
2.3 KiB
Rust
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
|
|
}
|