# Libraries
library(tidyverse)
# Read input from file
<- read_lines("../input/day24.txt", skip_empty_rows = TRUE) input
Day 24
Advent of Code: Worked Solutions
Setup
Part 1
Convert input string to a matrix of characters:
<- str_length(input[[1]])
w <- length(input)
h
<- input |>
mtx str_split("") |>
unlist() |>
matrix(nrow = h, byrow = TRUE)
Define helper functions to determine whether a map space is occupied at a given time. Hint from reddit user u/jaccomoc to scan rows/columns for blizzards at a certain time, rather than simulating the entire map at every time point:
# Define the constant start/end locations
<- c(row = 1, col = 2)
init <- c(row = h, col = w - 1)
target
# Wrap blizzards aroound the map edges
<- function(idx) (idx - 2) %% (w - 2) + 2
wrap_w <- function(idx) (idx - 2) %% (h - 2) + 2
wrap_h
# Check whether a given cell is open at a given time
<- function(idx, time) {
is_open <- idx[[1]]
row <- idx[[2]]
col wrap_w(col - time)] != '>' & mtx[wrap_h(row - time), col] != 'v' &
mtx[row, wrap_w(col + time)] != '<' & mtx[wrap_h(row + time), col] != '^'
mtx[row,
}
# Check whether a given cell is in the bounds of the map
<- function(idx) {
in_bounds <- idx[[1]]
row <- idx[[2]]
col
between(row, 2, h - 1) & between(col, 2, w - 1)) |
(all(idx == init) | all(idx == target)
}
Define a function that loops through time points and stops when the first elf reaches the target. Hint on use of “quantum elves” that die if standing on a blizzard spot from Reddit user u/SLiV9.
<- list(
moves c(row = 1, col = 0), # down
c(row = 0, col = 1), # right
c(row = -1, col = 0), # up
c(row = 0, col = -1), # left
c(row = 0, col = 0) # still
)
<- function(time_start, init, target) {
time_cross
<- list(init)
cur_locations <- time_start
t
repeat {
<- t + 1
t
<- cur_locations |>
cur_locations map(\(start) map(moves, \(move) start + move)) |>
flatten() |>
keep(in_bounds) |>
keep(partial(is_open, time = t)) |>
unique()
if (list(target) %in% cur_locations) break
}
t }
Run on puzzle input:
<- time_cross(0, init, target)
t1
t1
[1] 299
Part 2
Run the simulation again two more times, swapping the target and source locations, and starting where the last left off.
<- time_cross(t1, target, init)
t2 <- time_cross(t2, init, target)
t3
t3
[1] 899