From 6dab82d7ebd2edea2a1220cfbaff977528c6aaca Mon Sep 17 00:00:00 2001 From: cos Date: Sat, 5 Dec 2020 00:34:36 +0100 Subject: Refactor day04 to make full use of regex --- 2020/rust/day04/src/main.rs | 95 ++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 70 deletions(-) (limited to '2020') diff --git a/2020/rust/day04/src/main.rs b/2020/rust/day04/src/main.rs index 34ae9bc..0d4c901 100644 --- a/2020/rust/day04/src/main.rs +++ b/2020/rust/day04/src/main.rs @@ -50,81 +50,36 @@ fn part1(input: &[Passport]) -> usize { fn part2(input: &[Passport]) -> Result { let mut valid_count = 0; - let hgt_re = Regex::new(r"^(?P\d+)(?Pcm|in)$")?; - let hcl_re = Regex::new(r"^#[0-9a-f]{6}$")?; - let ecl_re = Regex::new(r"^(amb|blu|brn|gry|grn|hzl|oth)$")?; - let pid_re = Regex::new(r"^\d{9}$")?; + let mut re: HashMap = HashMap::new(); + + // byr (Birth Year) - four digits; at least 1920 and at most 2002. + re.insert(String::from("byr"), Regex::new(r"^(19[2-9][0-9])|(200[0-2])$")?); + // iyr (Issue Year) - four digits; at least 2010 and at most 2020. + re.insert(String::from("iyr"), Regex::new(r"^20(1[0-9])|(20)$")?); + // eyr (Expiration Year) - four digits; at least 2020 and at most 2030. + re.insert(String::from("eyr"), Regex::new(r"^20(2[0-9])|(30)$")?); + // hgt (Height) - a number followed by either cm or in: + // If cm, the number must be at least 150 and at most 193. + // If in, the number must be at least 59 and at most 76. + re.insert(String::from("hgt"), + Regex::new(r"^1(([5-8][0-9])|(9[0-3]))cm|((59)|(6[0-9])|(7[0-6]))in$")?); + // hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f. + re.insert(String::from("hcl"), Regex::new(r"^#[0-9a-f]{6}$")?); + // ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth. + re.insert(String::from("ecl"), Regex::new(r"^(amb|blu|brn|gry|grn|hzl|oth)$")?); + // pid (Passport ID) - a nine-digit number, including leading zeroes. + re.insert(String::from("pid"), Regex::new(r"^\d{9}$")?); + // cid (Country ID) - ignored, missing or not. 'validate: for passport in input { - // byr (Birth Year) - four digits; at least 1920 and at most 2002. - match passport.get("byr") { - Some(byr) => match byr.parse() { - Ok(1920..=2002) => {}, - _ => continue 'validate, - } - _ => continue 'validate, - } - // iyr (Issue Year) - four digits; at least 2010 and at most 2020. - match passport.get("iyr") { - Some(iyr) => match iyr.parse() { - Ok(2010..=2020) => {}, - _ => continue 'validate, - } - _ => continue 'validate, - } - // eyr (Expiration Year) - four digits; at least 2020 and at most 2030. - match passport.get("eyr") { - Some(eyr) => match eyr.parse() { - Ok(2020..=2030) => {}, + for key in &["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"] { + match (passport.get(*key), re.get(*key)) { + (Some(val), Some(re)) => if ! re.is_match(val) { + continue 'validate; + }, _ => continue 'validate, } - _ => continue 'validate, - } - // hgt (Height) - a number followed by either cm or in: - // If cm, the number must be at least 150 and at most 193. - // If in, the number must be at least 59 and at most 76. - match passport.get("hgt") { - Some(hgt) => match hgt_re.captures(hgt) { - Some(caps) => match &caps.name("unit") { - Some(unit) => match unit.as_str() { - "cm" => match &caps.name("value") { - Some(value) => match value.as_str().parse() { - Ok(150..=193) => {}, - _ => continue 'validate, - } - _ => continue 'validate, - }, - "in" => match &caps.name("value") { - Some(value) => match value.as_str().parse() { - Ok(59..=76) => {}, - _ => continue 'validate, - }, - _ => continue 'validate, - }, - _ => continue 'validate, - } - None => continue 'validate, - } - None => continue 'validate, - } - _ => continue 'validate, - } - // hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f. - match passport.get("hcl") { - Some(hcl) if hcl_re.is_match(hcl) => {}, - _ => continue 'validate, - } - // ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth. - match passport.get("ecl") { - Some(ecl) if ecl_re.is_match(ecl) => {}, - _ => continue 'validate, - } - // pid (Passport ID) - a nine-digit number, including leading zeroes. - match passport.get("pid") { - Some(pid) if pid_re.is_match(pid) => {}, - _ => continue 'validate, } - // cid (Country ID) - ignored, missing or not. valid_count += 1; } -- cgit v1.2.3