2020 AoC Day 4 – Passport Processing

This is a solution to Advent of Code 2020 day 4, written in Raku and Python.

https://adventofcode.com/2020/day/4

Part One

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 one of today's challenge can be implemented using sets. If we define a set of valid keys and a set of required keys, then rhe keys used in each passport must be a subset of the valid keys and a superset of the required keys.

Using a functional style, we reduce the entries to a sum of those where the condition holds true.

Raku

  my $valid-keys = < byr iyr eyr hgt hcl ecl pid cid >.Set;
  my $required-keys = $valid-keys (-) < cid >;

  my @entries = slurp('4-input.txt').split("\n\n"); # entries are separated by blank lines

  say [+] @entries.map(
      -> $e {
          my %fields = $e.trim.split(/\s+/).map(*.split(':')).flat;
          my $keys = %fields.keys.Set;

          $keys (<=) $valid-keys
          and
          $keys (>=) $required-keys
      })
260

Part Two

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?

Part two of the challenge requires us to extend the solution with a validity check for each of the expected fields.

Raku

  my $valid-keys = < byr iyr eyr hgt hcl ecl pid cid >.Set;
  my $required-keys = $valid-keys (-) < cid >;

  my @entries = slurp('4-input.txt').split("\n\n");

  say [+] @entries.map(
      -> $e {
          my %fields = $e.trim.split(/\s+/).map(*.split(':')).flat;
          my $keys = %fields.keys.Set;

          $keys (<=) $valid-keys
          and
          $keys (>=) $required-keys
          and
          %fields<byr> ~~ /^ (\d ** 4) $/ && 1920 <= $0 <= 2002
          and
          %fields<iyr> ~~ /^ (\d ** 4) $/ && 2010 <= $0 <= 2020
          and
          %fields<eyr> ~~ /^ (\d ** 4) $/ && 2020 <= $0 <= 2030
          and
          (
              %fields<hgt> ~~ /^ (\d+) 'cm' $/ && 150 <= $0 <= 193
              or
              %fields<hgt> ~~ /^ (\d+) 'in' $/ && 59 <= $0 <= 76
          )
          and
          %fields<hcl> ~~ /^ '#' <[ \d a..f ]> ** 6 $/
          and
          %fields<ecl> (elem) <amb blu brn gry grn hzl oth>.Set
          and
          %fields<pid> ~~ /^ \d ** 9 $/
          and
          True
      })
153
raku