Advent of Code 2020 Day 4
Task: Solve for X where...
X = the number of valid passports
- All required keys are present
- All values associated with required keys are correct
Example input
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
It represents:
- A list of passport data
- Each passport contains up to 8 key:value pairs
Part 1
- Considering three algorithmic ingredients
- Writing the algorithm
Considering three algorithmic ingredients
- Regular expression
- Length
- Includes
Regular expression
- For each passport, identify each of the eight keys
/(ecl|pid|eyr|hcl|byr|iyr|cid|hgt)/g
Length
- From the list of matches, check the count
- If it's 8, the passport must be valid
- If it's 6 or less, the passport must be invalid
Includes
- If it's 7, check for inclusion of
cid
as a key. - If it is, that means we're missing a required key, so it must be invalid
- If it isn't, then we must have all required keys, so the passport must be valid
Writing the algorithm
Split the input at each double-new-line character into an array of strings
For each item in the array of strings
Change the item to an array of matched keys found using the regular expression above
Filter the array of matched keys to only include 'true' values where:
1. The array's length is 8
2. The array's length is 7 and it doesn't include 'cid'
Return the length of the filtered array
Part 2
- A litany of utility functions and regular expressions
- Storing the functions as methods on an object
- Small addition to the root regular expression
- Writing a working algorithm
A litany of utility functions and regular expressions
- Beyond identifying passports with required keys present, I must now ensure their values are valid
- It seems I'll need utility functions and regular expressions to check each key's value
byr
iyr
eyr
are similar:
Return true if:
String length is 4
Value is within a range
hgt
is a regular expression, then a few checks:
Regular expression:
/(\d+)(\w+)/
Return true if:
String matches the regular expression
Depending on 'cm' or 'in', the value is within a range
hcl
is a regular expression:
/#([0-9a-f]{6})/
ecl
is a regular expression:
/(amb|blu|brn|gry|grn|hzl|oth){1}/
pid
is a regular expression:
/^\d{9}$/
cid
is always true.
Storing the functions as methods on an object
rules = {
byr()...,
hgt()...,
...
}
Each key:value pair match has this structure
['byr', '2000']
So I can run the test using:
rules[key](value)
Small addition to the root regular expression
Part 1 featured a regular expression to capture each key:
- Where each key could be one of eight 3-letter combinations
/(ecl|pid|eyr|hcl|byr|iyr|cid|hgt)/g
Part 2 requires a regular expression that captures key and value:
- Where value could be one or more letters, one or more digits, or a single hashtag
/(ecl|pid|eyr|hcl|byr|iyr|cid|hgt):([\w|\d|#]+)/g
Writing a working algorithm
Split the input at each double-new-line character into an array of strings
For each item in the array of strings
Change the item to an array of matched keys found using the updated regular expression above
Filter the array of matched keys to only include 'true' values where:
1. The array's length is 8
2. The array's length is 7 and it doesn't include 'cid'
Filter the array of valid - in that all required keys are present - passports to only include 'true' values where:
Every value for each key returns 'true' for the appropriate test found in the 'rules' object for that key
Return the length of the filtered array
I recall skipping this puzzle the first time I read it because I knew it would require regular expressions.
This time around, I felt delightfully comfortable building each RegEx.
It continues to feel rewarding when these early-day puzzles feel easier than anticipated.
Top comments (0)