Day 5

Advent of Code: Worked Solutions

About
Date

December 5, 2024

Setup

Import libraries:

library(tidyverse)
library(unglue)

Read text input from file:

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

Extract the page-ordering rules from the input:

rules <- input |> 
  unglue_data("{p1}|{p2}", convert = TRUE) |> 
  drop_na()

Extract the page sequences from the input:

pages <- input |>
  discard_at(1:nrow(rules)) |> 
  str_split(",") |> 
  map(parse_number)

Part 1

Define a function to sort a given vector of page numbers according to the rules that apply to those page numbers:

sort_by_rules <- function(seq) {
  active_rules <- rules |> 
    filter(p1 %in% seq & p2 %in% seq)
  
  repeat {
    swap_occurred <- FALSE
    for (i in 1:nrow(active_rules)) {
      rule <- filter(active_rules, row_number() == i)
      idx1 <- which(seq == rule$p1)
      idx2 <- which(seq == rule$p2)
      
      if (idx1 > idx2) {
        seq[[idx1]] <- rule$p2
        seq[[idx2]] <- rule$p1
        swap_occurred <- TRUE
      }
    }
    if (!swap_occurred) 
      return(seq)
  }
}

Sort all page sequences in the puzzle input and extract the center page of the result:

output <- pages |> 
  as_tibble_col(column_name = "update") |> 
  mutate(
    resorted = map(update, sort_by_rules),
    is_sorted = map2_lgl(update, resorted, identical),
    center_page = map_int(resorted, ~ .x[(length(.x) + 1) / 2])
  )

For all properly-ordered updates, sum the center page numbers:

output |>
  filter(is_sorted) |> 
  pull(center_page) |> 
  sum()

Part 2

For all improperly-ordered updates, sum their sorted center pages

output |>
  filter(!is_sorted) |> 
  pull(center_page) |> 
  sum()