# Libraries
library(tidyverse)
library(igraph)
# Read input from file
<- read_lines("../input/day16.txt", skip_empty_rows = TRUE) |>
input ::unglue_data(
ungluec(
"Valve {source} has flow rate={rate}; tunnels lead to valves {target}",
"Valve {source} has flow rate={rate}; tunnel leads to valve {target}"
),convert = TRUE
|>
) mutate(target = map(target, \(x) str_split_1(x, ", ")))
Day 16
Advent of Code: Worked Solutions
Setup
Part 1
Represent tunnels and valves as a graph:
<- input |>
g unnest(target) |>
pmap(function(source, target, ...) c(source, target)) |>
unique() |>
unlist() |>
make_graph(directed = TRUE) |>
as_undirected()
Get the list of valves with nonzero flow:
<- input |>
flows filter(rate > 0 | source == "AA") |>
select(source, rate) |>
deframe()
<- flows |>
non_init_flows discard_at("AA")
<- names(flows)
valves
<- distances(g, valves, valves) dists
List all permutations of possible valves to visit with a total distance less than 30:
<- function(choices, last, cur_length, max_length) {
get_path if (cur_length >= max_length)
return(head(last, -1))
if (length(choices) == 0)
return(last)
<- list()
ls for (valve in choices) {
<- append(
ls
ls, list(get_path(
!= valve],
choices[choices c(last, valve),
+ dists[tail(last, 1), valve] + 1,
cur_length
max_length
))
)
}|>
ls discard(is_null) |>
list_flatten() |>
unique()
}
<- get_path(names(non_init_flows), names(flows["AA"]), 0, 30) combos
Compute total pressure released for each permutation:
<- function(paths, max_time) {
get_pressures map_dbl(paths, \(path) {
<- tail(path, -1)
valve <- head(path, -1)
valve_lag <- tail(flows[path], -1)
flow
<- map2_int(valve_lag, valve, \(src, target) dists[src, target])
dist <- cumsum(dist) + 1:length(dist) + 1
time_start <- (max_time - time_start + 1) * flow
pressure
sum(pressure[time_start <= max_time])
})
}
<- get_pressures(combos, 30) pressures
Find the permutation that gives the maximum pressure:
<- which.max(pressures)
max_idx pressures[max_idx]
[1] 1947
Part 2
List all permutations of possible valves to visit with a total distance less than 26:
<- get_path(names(non_init_flows), names(flows["AA"]), 0, 26)
el_combos <- get_pressures(el_combos, 26) el_pressures
For each set of permutations, get the best pressure.
<- tibble(valves = map(el_combos, sort), pressure = el_pressures) |>
el_best slice_max(pressure, by = valves, with_ties = FALSE)
Get best combinations of permutations between yourself and the elephant:
|>
el_best rename(el_valves = valves, el_pressure = pressure) |>
pmap_dbl(\(el_valves, el_pressure) {
<- el_valves[el_valves != "AA"]
el_valves + el_best |>
el_pressure filter(map_lgl(valves, ~ length(intersect(.x, el_valves)) == 0)) |>
pull(pressure) |>
max()
|>
}) max()
[1] 2556