Day 21

Advent of Code: Worked Solutions

Puzzle Source
Puzzle Date

December 21, 2020

Setup

Import libraries:

library(tidyverse)
library(unglue)

Read text input from file:

input <- read_lines("../input/day21.txt", skip_empty_rows = TRUE)

Convert plain text input into lists of ingredients and allergens:

df <- input |> 
  unglue_data("{ingredient} (contains {allergen})") |> 
  mutate(
    food_id = row_number(),
    ingredient = str_split(ingredient, " "),
    allergen = str_split(allergen, ", ")
  ) |> 
  unnest_longer(ingredient) |> 
  unnest_longer(allergen)

Part 1

Iteratively pull ingredient-allergen pairs where one ingredient is the only option for a given allergen:

identified <- tibble(allergen = character(0), ingredient = character(0))

n_prv <- -1

while(n_prv != nrow(identified)) {
  n_prv <- nrow(identified)
  
  identified <- df |> 
    anti_join(identified, join_by(allergen)) |> 
    anti_join(identified, join_by(ingredient)) |> 
    summarize(n = n(), .by = c(allergen, ingredient)) |> 
    arrange(allergen, desc(n)) |> 
    slice_max(order_by = n, by = allergen) |> 
    filter(n() == 1, .by = allergen) |> 
    select(allergen, ingredient) |> 
    bind_rows(identified)
}

Count the number of times that non-allergen ingredients appear in the list:

df |> 
  anti_join(identified, join_by(ingredient)) |> 
  distinct(ingredient, food_id) |> 
  nrow()

Part 2

Arrange the allergen-containing ingredients alphabetically by allergen, then convert to a CSV string:

identified |> 
  arrange(allergen) |> 
  pull(ingredient) |> 
  str_flatten(",")