diff --git a/aoc2020/src/day04.rs b/aoc2020/src/day04.rs index 85c3445..b709db9 100644 --- a/aoc2020/src/day04.rs +++ b/aoc2020/src/day04.rs @@ -37,13 +37,17 @@ fn get_passports(input: &str) -> aoc::Result> { fn part1(input: &str) -> aoc::Result { let passports = get_passports(input)?; - Ok(passports.iter().filter(|p| p.has_valid_fields()).count()) + Ok(passports.iter().filter(|p| p.is_complete()).count()) } fn part2(input: &str) -> aoc::Result { let passports = get_passports(input)?; - Ok(passports.iter().filter(|p| p.is_valid()).count()) + Ok(passports + .into_iter() + .filter_map(|p| p.complete()) + .filter(|p| p.is_valid()) + .count()) } #[derive(Debug)] @@ -60,7 +64,7 @@ struct Passport { } impl Passport { - fn has_valid_fields(&self) -> bool { + fn is_complete(&self) -> bool { self.byr.is_some() && self.iyr.is_some() && self.eyr.is_some() @@ -70,113 +74,16 @@ impl Passport { && self.pid.is_some() } - fn is_valid(&self) -> bool { - self.byr_valid() - && self.iyr_valid() - && self.eyr_valid() - && self.hgt_valid() - && self.hcl_valid() - && self.ecl_valid() - && self.pid_valid() - } - - fn byr_valid(&self) -> bool { - let byr = match &self.byr { - Some(s) => s, - None => return false, - }; - - if let Ok(res) = byr.parse::() { - res >= 1920 && res <= 2002 - } else { - false - } - } - - fn iyr_valid(&self) -> bool { - let iyr = match &self.iyr { - Some(s) => s, - None => return false, - }; - - if let Ok(res) = iyr.parse::() { - res >= 2010 && res <= 2020 - } else { - false - } - } - - fn eyr_valid(&self) -> bool { - let eyr = match &self.eyr { - Some(s) => s, - None => return false, - }; - - if let Ok(res) = eyr.parse::() { - res >= 2020 && res <= 2030 - } else { - false - } - } - - fn hgt_valid(&self) -> bool { - let hgt = match &self.hgt { - Some(s) => s, - None => return false, - }; - - if let Some(num) = hgt.strip_suffix("in") { - if let Ok(res) = num.parse::() { - res >= 59 && res <= 76 - } else { - false - } - } else if let Some(num) = hgt.strip_suffix("cm") { - if let Ok(res) = num.parse::() { - res >= 150 && res <= 193 - } else { - false - } - } else { - false - } - } - - fn hcl_valid(&self) -> bool { - let hcl = match &self.hcl { - Some(s) => s, - None => return false, - }; - - if let Some(rest) = hcl.strip_prefix("#") { - rest.chars().filter(|c| !c.is_ascii_hexdigit()).count() == 0 - } else { - false - } - } - - fn ecl_valid(&self) -> bool { - let ecl = match &self.ecl { - Some(s) => s, - None => return false, - }; - - ecl == "amb" - || ecl == "blu" - || ecl == "brn" - || ecl == "gry" - || ecl == "grn" - || ecl == "hzl" - || ecl == "oth" - } - - fn pid_valid(&self) -> bool { - let pid = match &self.pid { - Some(s) => s, - None => return false, - }; - - pid.chars().filter(|c| !c.is_ascii_digit()).count() == 0 && pid.len() == 9 + fn complete(mut self) -> Option { + Some(CompletePassport { + byr: self.byr.take()?, + iyr: self.iyr.take()?, + eyr: self.eyr.take()?, + hgt: self.hgt.take()?, + hcl: self.hcl.take()?, + ecl: self.ecl.take()?, + pid: self.pid.take()?, + }) } } @@ -209,6 +116,92 @@ impl FromStr for Passport { } } +struct CompletePassport { + byr: String, + iyr: String, + eyr: String, + hgt: String, + hcl: String, + ecl: String, + pid: String, +} + +impl CompletePassport { + fn is_valid(&self) -> bool { + self.byr_valid() + && self.iyr_valid() + && self.eyr_valid() + && self.hgt_valid() + && self.hcl_valid() + && self.ecl_valid() + && self.pid_valid() + } + + fn byr_valid(&self) -> bool { + if let Ok(res) = self.byr.parse::() { + res >= 1920 && res <= 2002 + } else { + false + } + } + + fn iyr_valid(&self) -> bool { + if let Ok(res) = self.iyr.parse::() { + res >= 2010 && res <= 2020 + } else { + false + } + } + + fn eyr_valid(&self) -> bool { + if let Ok(res) = self.eyr.parse::() { + res >= 2020 && res <= 2030 + } else { + false + } + } + + fn hgt_valid(&self) -> bool { + if let Some(num) = self.hgt.strip_suffix("in") { + if let Ok(res) = num.parse::() { + res >= 59 && res <= 76 + } else { + false + } + } else if let Some(num) = self.hgt.strip_suffix("cm") { + if let Ok(res) = num.parse::() { + res >= 150 && res <= 193 + } else { + false + } + } else { + false + } + } + + fn hcl_valid(&self) -> bool { + if let Some(rest) = self.hcl.strip_prefix("#") { + rest.chars().filter(|c| !c.is_ascii_hexdigit()).count() == 0 + } else { + false + } + } + + fn ecl_valid(&self) -> bool { + self.ecl == "amb" + || self.ecl == "blu" + || self.ecl == "brn" + || self.ecl == "gry" + || self.ecl == "grn" + || self.ecl == "hzl" + || self.ecl == "oth" + } + + fn pid_valid(&self) -> bool { + self.pid.chars().filter(|c| !c.is_ascii_digit()).count() == 0 && self.pid.len() == 9 + } +} + #[cfg(test)] mod tests { use super::*;