Day 5

Advent of Code: Worked Solutions

About
Date

December 5, 2024

Setup

# Libraries
library(tidyverse)

# Read input from file
input <- read_lines("../input/day05.txt", skip_empty_rows = TRUE)

Part 1

# Extract page ordering rules from input
rule_list <- input |> 
  keep(~ str_detect(.x, "\\|")) |> 
  as_tibble_col(column_name = "rule") |> 
  separate(rule, into = c("p1", "p2")) |> 
  mutate(rule_num = row_number(), .before = everything()) |> 
  mutate(across(c(p1, p2), parse_number))

# Extract page sequences from input
pages <- input |> 
  discard(~ str_detect(.x, "\\|")) |> 
  str_split(",") |> 
  map(parse_number) |> 
  as_tibble_col(column_name = "update")

# Sort a given vector by its applicable rules
sort_by_rules <- function(seq) {
  active_rules <- rule_list |> 
    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 and extract the center page of each result
output <- pages |> 
  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 the properly-ordered updates, sum the center page numbers
output |>
  filter(is_sorted) |> 
  pull(center_page) |> 
  sum()
[1] 6505

Part 2

# For the improperly-ordered updates, sum their sorted center pages
output |>
  filter(!is_sorted) |> 
  pull(center_page) |> 
  sum()
[1] 6897