diff options
Diffstat (limited to '2020/day-04/README.org')
-rw-r--r-- | 2020/day-04/README.org | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/2020/day-04/README.org b/2020/day-04/README.org new file mode 100644 index 0000000..5456971 --- /dev/null +++ b/2020/day-04/README.org @@ -0,0 +1,211 @@ +#+SETUPFILE: ~/.emacs.d/org-templates/level-3.org +#+HTML_LINK_UP: ../../index.html#2020 +#+OPTIONS: toc:1 +#+EXPORT_FILE_NAME: index +#+TITLE: Day 04 - Passport Processing + +* Puzzle +- This puzzle is taken from: https://adventofcode.com/2020/day/4 + +You arrive at the airport only to realize that you grabbed your North +Pole Credentials instead of your passport. While these documents are +extremely similar, North Pole Credentials aren't issued by a country and +therefore aren't actually valid documentation for travel in most of the +world. + +It seems like you're not the only one having problems, though; a very +long line has formed for the automatic passport scanners, and the delay +could upset your travel itinerary. + +Due to some questionable network security, you realize you might be able +to solve both of these problems at the same time. + +The automatic passport scanners are slow because they're having trouble +detecting which passports have all required fields. The expected fields +are as follows: + +- =byr= (Birth Year) +- =iyr= (Issue Year) +- =eyr= (Expiration Year) +- =hgt= (Height) +- =hcl= (Hair Color) +- =ecl= (Eye Color) +- =pid= (Passport ID) +- =cid= (Country ID) + +Passport data is validated in batch files (your puzzle input). Each +passport is represented as a sequence of key:value pairs separated by +spaces or newlines. Passports are separated by blank lines. + +Here is an example batch file containing four passports: +#+BEGIN_SRC +ecl:gry pid:860033327 eyr:2020 hcl:#fffffd +byr:1937 iyr:2017 cid:147 hgt:183cm + +iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 +hcl:#cfa07d byr:1929 + +hcl:#ae17e1 iyr:2013 +eyr:2024 +ecl:brn pid:760753108 byr:1931 +hgt:179cm + +hcl:#cfa07d eyr:2025 pid:166559648 +iyr:2011 ecl:brn hgt:59in +#+END_SRC + +The first passport is valid - all eight fields are present. The second +passport is invalid - it is missing hgt (the Height field). + +The third passport is interesting; the only missing field is cid, so it +looks like data from North Pole Credentials, not a passport at all! +Surely, nobody would mind if you made the system temporarily ignore +missing cid fields. Treat this "passport" as valid. + +The fourth passport is missing two fields, cid and byr. Missing cid is +fine, but missing any other field is not, so this passport is invalid. + +According to the above rules, your improved system would report 2 valid +passports. + +Count the number of valid passports - those that have all required +fields. Treat cid as optional. In your batch file, how many passports +are valid? +** Part 2 +The line is moving more quickly now, but you overhear airport security +talking about how passports with invalid data are getting through. +Better add some data validation, quick! + +You can continue to ignore the cid field, but each other field has +strict rules about what values are valid for automatic validation: + +- =byr= (Birth Year) - four digits; at least 1920 and at most 2002. +- =iyr= (Issue Year) - four digits; at least 2010 and at most 2020. +- =eyr= (Expiration Year) - four digits; at least 2020 and at most 2030. +- =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=. +- =hcl= (Hair Color) - a =#= followed by exactly six characters =0-9= or =a-f=. +- =ecl= (Eye Color) - exactly one of: =amb= =blu= =brn= =gry= =grn= =hzl= =oth=. +- =pid= (Passport ID) - a nine-digit number, including leading zeroes. +- =cid= (Country ID) - ignored, missing or not. + +Your job is to count the passports where all required fields are both +present and valid according to the above rules. Here are some example +values: +#+BEGIN_SRC +byr valid: 2002 +byr invalid: 2003 + +hgt valid: 60in +hgt valid: 190cm +hgt invalid: 190in +hgt invalid: 190 + +hcl valid: #123abc +hcl invalid: #123abz +hcl invalid: 123abc + +ecl valid: brn +ecl invalid: wat + +pid valid: 000000001 +pid invalid: 0123456789 +#+END_SRC + +Here are some invalid passports: +#+BEGIN_SRC +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 +#+END_SRC + +Here are some valid passports: +#+BEGIN_SRC +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 +#+END_SRC + +Count the number of valid passports - those that have all required +fields and valid values. Continue to treat cid as optional. In your +batch file, how many passports are valid? +* Solution +The input file is split by =\n\n= & stored in =@passports=. We iterate over +=@passports= & seperate each field in =%field=. Then we check if all +required fields are present, if not then skip the passport. If true then +increment =$valid_passports= which holds the number of valid passports. + +#+BEGIN_SRC raku +my $input = slurp "input"; +my @passports = $input.split("\n\n"); +my $valid_passports = 0; + +MAIN: for @passports -> $passport { + my %fields; + + for $passport.words -> $field { + my ($key, $value) = $field.split(":"); + %fields{$key} = $value; + } + + # Check for fields that are strictly required. `cid' can be + # skipped. Skip this passport if it's not valid. + for <byr iyr eyr hgt hcl ecl pid> -> $field { + next MAIN unless %fields{$field}; + } + + # Do validation in part 2. + if $part == 2 { + ... + } + $valid_passports++; +} +say "Part $part: " ~ $valid_passports; +#+END_SRC +** Part 2 +For part 2, more validation is performed. The rules are simple & +well-defined in Puzzle section. + +I had forgotten the =default= block in =given/when= & that meant it was +counting passports which don't have =hgt= set to either =cm= or =in= as valid. +In my case it was a single passport. + +#+BEGIN_SRC raku +next MAIN unless ( + (1920 ≤ %fields{<byr>} ≤ 2002) + and (2010 ≤ %fields{<iyr>} ≤ 2020) + and (2020 ≤ %fields{<eyr>} ≤ 2030) + and (<amb blu brn gry grn hzl oth> ∋ %fields{<ecl>}) + and (%fields{<pid>} ~~ /^\d ** 9$/) + and (%fields{<hcl>} ~~ /^'#' <[\d a..f]> ** 6/) +); +given substr(%fields{<hgt>}, *-2) { + when 'cm' { + next MAIN unless 150 ≤ substr(%fields{<hgt>}, 0, *-2) ≤ 193; + } + when 'in' { + next MAIN unless 59 ≤ substr(%fields{<hgt>}, 0, *-2) ≤ 76; + } + default { next MAIN; } +} +#+END_SRC |