library(tidyverse)
Day 12
Advent of Code: Worked Solutions
Setup
Import libraries:
Read input from file:
<- read_delim(
input "../input/day12.txt",
delim = '-',
col_names = c("source", "target"),
show_col_types = FALSE
)
Part 1
Convert input to a data frame of edges for every vertex (disallowing returns to the “start” vertex and departures from the “end” vertex):
<- bind_rows(
adj
input,select(input, target = source, source = target)
|>
) filter(target != "start" & source != "end") |>
arrange(source, target)
<- adj$source |>
small_caves keep(~ .x == str_to_lower(.x)) |>
discard(~ .x == "start") |>
unique()
Beginning from the ‘start’ node, expand outward until the ‘end’ node is found in each tree. End the search early if a small cave is visited more than once or no valid options remain.
<- function(path) {
invalid any(duplicated(keep(path, ~ .x %in% small_caves)))
}
<- function(adj, cur_path = "start") {
find_paths
<- tail(cur_path, 1)
src
if (src == "end")
return(list(cur_path))
if (invalid(cur_path))
return(list())
<- list()
paths <- adj |>
nxt filter(source == src) |>
pull(target)
for (vtx in nxt)
<- c(paths, find_paths(adj, c(cur_path, vtx)))
paths
return(paths)
}
Compute the total number of paths for the puzzle input:
find_paths(adj) |>
length()
Part 2
Modify the invalid
function to allow up to two visits to any one small cave:
<- function(path) {
invalid <- path |>
counts keep(~ .x %in% small_caves) |>
sort() |>
rle()
max(counts$lengths) > 2 | sum(counts$lengths == 2) > 1
}
Re-run on puzzle input:
find_paths(adj) |>
length()