library(tidyverse)
library(unglue)Day 4
Advent of Code: Worked Solutions
Setup
Import libraries:
Read text input from file and separate into lists of key-value pairs:
input <- read_lines("../input/day04.txt")Part 1
Convert text input to a data frame of key value-pairs, enumerated according to the blank lines, and determine whether each passport has all requied fields (ignoring “cid”):
byr (Birth Year)
iyr (Issue Year)
eyr (Expiration Year)
hgt (Height)
hcl (Hair Color)
ecl (Eye Color)
pid (Passport ID)
cid (Country ID)
required_keys <- c("byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid")
df <- input |>
# Convert text lines to data frame
str_flatten(collapse = "\n") |>
str_split_1("\n\n") |>
str_split("\\s") |>
imap_dfr(\(str, idx) {
str |>
unglue_data("{key}:{value}") |>
mutate(idx = idx)
}) |>
# Flag whether each passpord is valid or not
mutate(
is_valid = sum(key %in% required_keys) == 7,
.by = idx
)Count the total valid passpords:
df |>
filter(is_valid) |>
distinct(idx) |>
nrow()Part 2
Filter to the passports with all required fields, validate those fields, and count the final number of valid results:
df |>
filter(is_valid & key %in% required_keys) |>
mutate(
is_valid = (
(
key == "byr"
& str_length(value) == 4
& between(parse_number(value), 1920, 2002)
) | (
key == "iyr"
& str_length(value) == 4
& between(parse_number(value), 2010, 2020)
) | (
key == "eyr"
& str_length(value) == 4
& between(parse_number(value), 2020, 2030)
) | (
key == "hgt"
& str_detect(value, "^\\d+cm$")
& between(parse_number(value), 150, 193)
) | (
key == "hgt"
& str_detect(value, "^\\d+in$")
& between(parse_number(value), 59, 76)
) | (
key == "hcl"
& str_detect(value, "^#[0-9a-f]{6}$")
) | (
key == "ecl"
& value %in% c("amb", "blu", "brn", "gry", "grn", "hzl", "oth")
) | (
key == "pid"
& str_detect(value, "^\\d{9}$")
)
)
) |>
filter(all(is_valid), .by = idx) |>
distinct(idx) |>
nrow()