summary refs log tree commit diff stats
path: root/2020/day-04/README.org
diff options
context:
space:
mode:
Diffstat (limited to '2020/day-04/README.org')
-rw-r--r--2020/day-04/README.org211
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