2020: day04: part 2

This commit is contained in:
Antoine Martin 2020-12-04 10:43:43 +01:00
parent 20e3f6c1a9
commit ab5efad22e
4 changed files with 156 additions and 2 deletions

View file

@ -0,0 +1,13 @@
eyr:1972 cid:100
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
iyr:2019
hcl:#602927 eyr:1967 hgt:170cm
ecl:grn pid:012533040 byr:1946
hcl:dab227 iyr:2012
ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
hgt:59cm ecl:zzz
eyr:2038 hcl:74454a iyr:2023
pid:3556412378 byr:2007

View file

@ -0,0 +1,12 @@
pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
hcl:#623a2f
eyr:2029 ecl:blu cid:129 byr:1989
iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
hcl:#888785
hgt:164cm byr:2001 iyr:2015 cid:88
pid:545766238 ecl:hzl
eyr:2022
iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719

View file

@ -8,6 +8,7 @@ pub fn run() -> aoc::Result<String> {
let mut res = String::with_capacity(128);
writeln!(res, "part 1: {}", part1(INPUT)?)?;
writeln!(res, "part 2: {}", part2(INPUT)?)?;
Ok(res)
}
@ -39,6 +40,12 @@ fn part1(input: &str) -> aoc::Result<usize> {
Ok(passports.iter().filter(|p| p.has_valid_fields()).count())
}
fn part2(input: &str) -> aoc::Result<usize> {
let passports = get_passports(input)?;
Ok(passports.iter().filter(|p| p.is_valid()).count())
}
#[derive(Debug)]
struct Passport {
byr: Option<String>,
@ -62,6 +69,115 @@ impl Passport {
&& self.ecl.is_some()
&& 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::<i64>() {
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::<i64>() {
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::<i64>() {
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::<i64>() {
res >= 59 && res <= 76
} else {
false
}
} else if let Some(num) = hgt.strip_suffix("cm") {
if let Ok(res) = num.parse::<i64>() {
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
}
}
impl FromStr for Passport {
@ -97,15 +213,28 @@ impl FromStr for Passport {
mod tests {
use super::*;
static PROVIDED: &'static str = include_str!("../input/day04_provided.txt");
static PROVIDED1: &'static str = include_str!("../input/day04_provided1.txt");
static PROVIDED2: &'static str = include_str!("../input/day04_provided2.txt");
static PROVIDED3: &'static str = include_str!("../input/day04_provided3.txt");
#[test]
fn part1_provided() {
assert_eq!(part1(PROVIDED).unwrap(), 2);
assert_eq!(part1(PROVIDED1).unwrap(), 2);
}
#[test]
fn part1_real() {
assert_eq!(part1(INPUT).unwrap(), 192);
}
#[test]
fn part2_provided() {
assert_eq!(part2(PROVIDED2).unwrap(), 0);
assert_eq!(part2(PROVIDED3).unwrap(), 4);
}
#[test]
fn part2_real() {
assert_eq!(part2(INPUT).unwrap(), 101);
}
}