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