library(tidyverse)
library(unglue)
Day 13
Advent of Code: Worked Solutions
Setup
Import libraries:
Disable scientific formatting when displaying large numbers:
options(scipen = 999)
Read input from file:
<- read_lines("../input/day13.txt", skip_empty_rows = TRUE) input
Extract numerical values from text input into a data frame:
<- input |>
df unglue_data(c(
"Button {button}: X+{x=\\d+}, Y+{y=\\d+}",
"{button}: X={x=\\d+}, Y={y=\\d+}"
|>
)) mutate(
machine_id = floor((row_number() - 1) / 3),
across(c(x, y), parse_number),
.before = everything()
|>
) pivot_wider(names_from = button, values_from = c(x, y))
Part 1
Define a function to convert numeric equation input and output token counts:
<- function(df) {
compute_tokens
# Convert each machine's properties into a system of equations and solve.
<- df |>
soln nest(coeff = c(x_A, x_B, y_A, y_B)) |>
nest(intercept = c(x_Prize, y_Prize)) |>
mutate(
coeff = map(coeff, ~ matrix(as.numeric(.x), nrow = 2, byrow = TRUE)),
intercept = map(intercept, as.numeric),
soln = map2(
coeff,
intercept, ~ solve(.x, .y) |>
set_names("A", "B") |>
as_tibble_row()
)|>
) unnest(soln) |>
select(machine_id, A, B)
# Check that the solution is two whole numbers, then sum the token cost
|>
soln mutate(
across(
c(A, B),
~ near(.x, abs(round(.x)), tol = 0.001),
.names = "{.col}_valid"
),win = A_valid & B_valid,
tokens = if_else(win, 3 * A + B, 0)
|>
) pull(tokens) |>
sum()
}
Run function on puzzle input:
compute_tokens(df)
Part 2
Add 10000000000000 to each prize intercept and re-compute:
|>
df mutate(across(c(x_Prize, y_Prize), ~ .x + 10000000000000)) |>
compute_tokens()