123 lines
3.1 KiB
Rust
123 lines
3.1 KiB
Rust
use std::collections::HashMap;
|
|
use std::error::Error;
|
|
use std::fs::File;
|
|
use std::io::{self, BufRead};
|
|
use std::vec::Vec;
|
|
|
|
#[macro_use]
|
|
extern crate lazy_static;
|
|
extern crate regex;
|
|
|
|
use regex::Regex;
|
|
|
|
fn is_valid(passport: &HashMap<String, String>) -> u32 {
|
|
lazy_static! {
|
|
static ref HCL_RE: Regex = Regex::new(r"^#[a-f0-9]{6}$").unwrap();
|
|
static ref PID_RE: Regex = Regex::new(r"^[0-9]{9}$").unwrap();
|
|
static ref ECL_RE: Regex = Regex::new(r"^(amb|blu|brn|gry|grn|hzl|oth)$").unwrap();
|
|
static ref HGT_RE: Regex = Regex::new(r"^([0-9]+)(in|cm)$").unwrap();
|
|
}
|
|
|
|
if !passport.contains_key("byr")
|
|
|| !passport.contains_key("iyr")
|
|
|| !passport.contains_key("eyr")
|
|
|| !passport.contains_key("hgt")
|
|
|| !passport.contains_key("hcl")
|
|
|| !passport.contains_key("ecl")
|
|
|| !passport.contains_key("pid")
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
if let Ok(year) = passport.get("byr").unwrap().parse::<u32>() {
|
|
if year < 1920 || year > 2002 {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
if let Ok(year) = passport.get("iyr").unwrap().parse::<u32>() {
|
|
if year < 2010 || year > 2020 {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
if let Ok(year) = passport.get("eyr").unwrap().parse::<u32>() {
|
|
if year < 2020 || year > 2030 {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
if !HCL_RE.is_match(passport.get("hcl").unwrap()) {
|
|
return 0;
|
|
}
|
|
|
|
if let Some(cap) = HGT_RE.captures_iter(passport.get("hgt").unwrap()).nth(0) {
|
|
if let Ok(hgt) = cap[1].parse::<u32>() {
|
|
match &cap[2] {
|
|
"in" => {
|
|
if hgt < 59 || hgt > 76 {
|
|
return 0;
|
|
}
|
|
}
|
|
"cm" => {
|
|
if hgt < 150 || hgt > 193 {
|
|
return 0;
|
|
}
|
|
}
|
|
_ => return 0,
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
if !ECL_RE.is_match(passport.get("ecl").unwrap()) {
|
|
return 0;
|
|
}
|
|
|
|
if !PID_RE.is_match(passport.get("pid").unwrap()) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
let file = File::open("inputs/day4.txt")?;
|
|
let lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
|
|
|
let mut passports: Vec<HashMap<String, String>> = Vec::new();
|
|
let mut passport = HashMap::<String, String>::new();
|
|
for line in lines {
|
|
if line == "" {
|
|
passports.push(passport);
|
|
passport = HashMap::new();
|
|
continue;
|
|
}
|
|
|
|
for tuple in line.split(" ") {
|
|
let mut parts = tuple.split(":");
|
|
let key = parts.nth(0).unwrap().to_string();
|
|
let value = parts.nth(0).unwrap().to_string();
|
|
passport.insert(key, value);
|
|
}
|
|
}
|
|
passports.push(passport);
|
|
|
|
println!("Read {} passports.", passports.len());
|
|
|
|
let count = passports.iter().map(is_valid).fold(0, |acc, x| acc + x);
|
|
|
|
println!("Valid count {}", count);
|
|
|
|
Ok(())
|
|
}
|