# Libraries
library(tidyverse)
# Read input from file
<- read_lines("../input/day16.txt", skip_empty_rows = TRUE) input
Day 16
Advent of Code: Worked Solutions
Setup
Part 1
Convert text input to a character matrix:
<- input |>
mtx str_split("") |>
map(~ matrix(.x, nrow = 1)) |>
reduce(rbind)
Define a function that converts a direction, direction index, and sublocation along that direction into standard row/column form, then into a single ID value:
<- function(dir, vec_idx, loc_idx) {
mtx_id <- case_match(dir, c('W', 'E') ~ vec_idx, c('N', 'S') ~ loc_idx)
row <- case_match(dir, c('W', 'E') ~ loc_idx, c('N', 'S') ~ vec_idx)
col
- 1) * ncol(mtx) + col
(row }
Define a function that tracks the beam through the matrix and returns the IDs of the elements visited:
<- function(dir, vec_idx = 1, start_idx, visited) {
beam
if (!between(start_idx, 1, nrow(mtx))) return(visited)
# Initialize
<- if (dir %in% c('W', 'E')) mtx[vec_idx,] else mtx[,vec_idx]
vec
<- case_match(dir, c('E', 'S') ~ length(vec), c('N', 'W') ~ 1)
end_idx <- case_match(dir, c('W', 'E') ~ '|', c('N', 'S') ~ '-')
chr_split <- case_match(dir, c('N', 'W') ~ '\\', c('S', 'E') ~ '/')
chr_turn_neg <- case_match(dir, c('N', 'W') ~ '/', c('S', 'E') ~ '\\')
chr_turn_pos <- case_match(dir, c('W', 'E') ~ 'N', c('N', 'S') ~ 'W')
dir_split_1 <- case_match(dir, c('W', 'E') ~ 'S', c('N', 'S') ~ 'E')
dir_split_2 <- case_match(dir, c('N', 'S') ~ 'W', c('W', 'E') ~ 'N')
dir_turn_neg <- case_match(dir, c('N', 'S') ~ 'E', c('W', 'E') ~ 'S')
dir_turn_pos
for (i in start_idx:end_idx) {
<- mtx_id(dir, vec_idx, i)
id
if (id %in% visited[[dir]])
return(visited)
else
<- c(visited[[dir]], id)
visited[[dir]]
if (vec[[i]] == chr_split) {
<- beam(dir_split_1, i, vec_idx - 1, visited)
visited <- beam(dir_split_2, i, vec_idx + 1, visited)
visited break
}else if (vec[[i]] == chr_turn_neg) {
<- beam(dir_turn_neg, i, vec_idx - 1, visited)
visited break
}else if (vec[[i]] == chr_turn_pos) {
<- beam(dir_turn_pos, i, vec_idx + 1, visited)
visited break
}
}
visited }
Starting from upper left, loop through the matrix and count the number of energized tiles:
<- map(set_names(c("N", "S", "W", "E")), ~ c())
init_visited
beam("E", vec_idx = 1, start_idx = 1, visited = init_visited) |>
unlist() |>
unique() |>
length()
[1] 7046
Part 2
If the beam can enter from any edge, find the maximum number of energizable tiles:
<- function(dir, vec_idx, start_idx) {
energize_from beam(dir, vec_idx, start_idx, init_visited) |>
unlist() |>
unique() |>
length()
}
expand_grid(dir = c('N', 'S', 'W', 'E'), vec = 1:nrow(mtx)) |>
mutate(start = case_match(dir, c('S', 'E') ~ 1, c('N', 'W') ~ nrow(mtx))) |>
pmap_dbl(\(dir, vec, start) energize_from(dir, vec, start)) |>
max()
[1] 7313