library(tidyverse)
library(unglue)
Day 8
Advent of Code: Worked Solutions
Setup
Import libraries:
Read text input from file and parse into a dataframe of character operations and integer arguments:
<- read_lines("../input/day08.txt") |>
input unglue_data("{op} {arg}", convert = TRUE) |>
deframe()
Part 1
Define a function to loop through the instructions in the input, break whenever an instruction is visited for a second time, and return the accumulator value at that time:
<- function(instructions) {
find_loop
<- rep(FALSE, length(instructions))
visited <- 0
acc <- 1
i
while (i <= length(instructions)) {
if (visited[i]) {
return(acc)
else {
} <- TRUE
visited[i]
}
<- names(instructions)[[i]]
op <- instructions[[i]]
arg
if (op == "nop") {
<- i + 1
i else if (op == "acc") {
} <- acc + arg
acc <- i + 1
i else if (op == "jmp") {
} <- i + arg
i
}
}
return(NA)
}
Run on puzzle input:
find_loop(input)
Part 2
Swap each jmp
and nop
operation one-by-one and see which swap results in a valid output (no loop):
<- map(
instr_mod which(names(input) %in% c("jmp", "nop")),
\(idx) {|>
input set_names(modify_at(
names(input),
idx, ~ case_match(.x, "jmp" ~ "nop", "nop" ~ "jmp")
))
}
)
<- instr_mod |>
idx_mod map_dbl(find_loop) |>
detect_index(is.na)
Modify the find_loop
function to run the instructions and return the final value of the accumulator:
<- function(instructions) {
run_instr <- 0
acc <- 1
i
while (i <= length(instructions)) {
<- names(instructions)[[i]]
op <- instructions[[i]]
arg
if (op == "nop") {
<- i + 1
i else if (op == "acc") {
} <- acc + arg
acc <- i + 1
i else if (op == "jmp") {
} <- i + arg
i
}
}
return(acc)
}
Run on the valid modified index:
run_instr(instr_mod[[idx_mod]])