1
0
mirror of https://github.com/chylex/Advent-of-Code.git synced 2025-05-26 03:34:06 +02:00

Add 2020 - Day 4 - Part 2

This commit is contained in:
chylex 2022-02-23 14:19:32 +01:00
parent aaec7168fb
commit bac7d97b9a
Signed by: chylex
GPG Key ID: 4DE42C8F19A80548

View File

@ -12,8 +12,9 @@ fn main() -> Result<(), Box<dyn Error>> {
let lines = utils::read_input_lines()?;
let passports = load_passports(&lines)?;
let valid_passports = passports.iter().filter(|p| p.is_valid_or_from_north_pole()).count();
println!("Valid passports: {}", valid_passports);
let passports = passports.into_iter().filter(|p| p.is_valid_or_from_north_pole()).collect::<Vec<Passport>>();
println!("Valid passports with no field validation: {}", passports.len());
println!("Valid passports with field validation: {}", passports.iter().filter(|p| p.are_field_values_valid()).count());
Ok(())
}
@ -61,24 +62,41 @@ impl PassportField {
_ => None
}
}
fn is_value_valid(&self, value: &str) -> bool {
fn as_u32(value: &str) -> Option<u32> {
value.parse().ok()
}
fn as_u32_with_unit(value: &str, unit: &str) -> Option<u32> {
value.strip_suffix(unit).and_then(as_u32)
}
match self {
PassportField::BirthYear => as_u32(value).filter(|year| *year >= 1920 && *year <= 2002).is_some(),
PassportField::IssueYear => as_u32(value).filter(|year| *year >= 2010 && *year <= 2020).is_some(),
PassportField::ExpirationYear => as_u32(value).filter(|year| *year >= 2020 && *year <= 2030).is_some(),
PassportField::Height => {
if let Some(height) = as_u32_with_unit(value, "cm") {
height >= 150 && height <= 193
} else if let Some(height) = as_u32_with_unit(value, "in") {
height >= 59 && height <= 76
} else {
false
}
}
PassportField::HairColor => value.strip_prefix('#').filter(|hex| hex.chars().all(|c| c.is_digit(16))).is_some(),
PassportField::EyeColor => VALID_EYE_COLORS.contains(value),
PassportField::PassportId => value.len() == 9 && value.chars().all(|c| c.is_ascii_digit()),
PassportField::CountryId => true
}
}
}
struct Passport {
fields: HashMap<PassportField, String>,
}
lazy_static! {
static ref REQUIRED_FIELDS: HashSet<PassportField> = HashSet::from([
PassportField::BirthYear,
PassportField::IssueYear,
PassportField::ExpirationYear,
PassportField::Height,
PassportField::HairColor,
PassportField::EyeColor,
PassportField::PassportId
]);
}
impl Passport {
fn new() -> Passport {
Passport { fields: HashMap::new() }
@ -98,4 +116,24 @@ impl Passport {
let fields = &self.fields.keys().map(|f| *f).collect::<HashSet<PassportField>>();
return fields.is_superset(&REQUIRED_FIELDS);
}
fn are_field_values_valid(&self) -> bool {
return self.fields.iter().all(|(field, value)| field.is_value_valid(value.as_str()));
}
}
lazy_static! {
static ref REQUIRED_FIELDS: HashSet<PassportField> = HashSet::from([
PassportField::BirthYear,
PassportField::IssueYear,
PassportField::ExpirationYear,
PassportField::Height,
PassportField::HairColor,
PassportField::EyeColor,
PassportField::PassportId
]);
static ref VALID_EYE_COLORS: HashSet<&'static str> = HashSet::from([
"amb", "blu", "brn", "gry", "grn", "hzl", "oth"
]);
}