Day 4 solution
[?]
Dec 16, 2020, 11:57 PM
RSO3CMWGWGW73HBTR5LZJR5N4KFWDE7WVHN4RAFDQNOYMHSS2KTACDependencies
- [2]
B527MN66Solve day 1 for 2020
Change contents
- file addition: day4.rs[2.17]
use std::collections::HashMap;use std::env;fn extract_keys<S: AsRef<str>>(ln: S) -> HashMap<String,String> {let mut collected = HashMap::new();for field in ln.as_ref().split_whitespace() {let parts: Vec<_> = field.split(':').collect();collected.insert(String::from(parts[0]), String::from(parts[1]));};collected}const REQUIRED: &[(&str, fn(String) -> bool)] =&[("byr", check_byr),("iyr", check_iyr),("eyr", check_eyr),("hgt", check_hgt),("hcl", check_hcl),("ecl", check_ecl),("pid", check_pid)];fn check_byr(ln: String) -> bool {ln.len() == 4 && match ln.parse::<usize>() {Ok(year) => year >= 1920 && year <= 2002,Err(_) => false,}}fn check_iyr(ln: String) -> bool {ln.len() == 4 && match ln.parse::<usize>() {Ok(year) => year >= 2010 && year <= 2020,Err(_) => false,}}fn check_eyr(ln: String) -> bool {ln.len() == 4 && match ln.parse::<usize>() {Ok(year) => year >= 2020 && year <= 2030,Err(_) => false,}}fn check_hgt(ln: String) -> bool {match ln.find(|c: char| !c.is_digit(10)) {Some(sep) => {let (num, unit) = ln.split_at(sep);match num.parse::<isize>() {Ok(num) => {if unit == "in" {num >= 59 && num <= 76} else if unit == "cm" {num >= 150 && num <= 193} else {false}},Err(_) => false,}},None => false,}}fn check_hcl(ln: String) -> bool {if ln.len() != 7 {return false;}let mut ci = ln.chars();if ci.next() != Some('#') {return false;}for c in ci {if !c.is_digit(16) {return false;}}true}fn check_ecl(ln: String) -> bool {for ex in ["amb","blu","brn","gry","grn","hzl","oth"].iter() {if ln == *ex {return true;}}false}fn check_pid(ln: String) -> bool {ln.len() == 9 && ln.chars().all(|c| c.is_digit(10))}#[derive(Clone,Copy,Debug)]enum Document {Passport,NorthPole,Invalid}struct DelimByEmpty<I> {inner: I,}impl<I> DelimByEmpty<I> {fn new(inner: I) -> Self {DelimByEmpty { inner: inner }}}impl<I: Iterator<Item=HashMap<Q,R>>, Q: Clone + std::cmp::Eq + std::hash::Hash, R: Clone> Iterator for DelimByEmpty<I> {type Item = HashMap<Q,R>;fn next(&mut self) -> Option<Self::Item> {let mut result = HashMap::new();loop {match self.inner.next() {None => {if result.is_empty() {return None;} else {return Some(result);}},Some(line) => {if line.is_empty() {return Some(result);} else {for (key,val) in line.iter() {result.insert(key.clone(), val.clone());}}},}}}}fn validate_line(found: HashMap<String,String>, version: usize) -> Document {for (key,validator) in REQUIRED.iter() {match found.get(&String::from(*key)) {None => { return Document::Invalid; },Some(value) => {if version == 2 && !validator(value.clone()) {return Document::Invalid;}},}};if found.contains_key(&String::from("cid")) {Document::Passport} else {Document::NorthPole}}fn main() {use std::io::BufRead;let args: Vec<_> = env::args().collect();let version: usize = args[2].parse().unwrap();let result: i32 = DelimByEmpty::new(std::io::BufReader::new(std::fs::File::open(&args[1]).unwrap()).lines().map(Result::unwrap).map(extract_keys)).map(|d| validate_line(d, version)).map(|t| match t {Document::Invalid => 0,_ => 1,}).sum();println!("{:}",result);}