You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.0 KiB
162 lines
4.0 KiB
# --- Day 8: Handheld Halting ---
|
|
#
|
|
# Your flight to the major airline hub reaches cruising altitude without
|
|
# incident. While you consider checking the in-flight menu for one of those
|
|
# drinks that come with a little umbrella, you are interrupted by the kid
|
|
# sitting next to you.
|
|
#
|
|
# Their handheld game console won't turn on! They ask if you can take a look.
|
|
#
|
|
# You narrow the problem down to a strange infinite loop in the boot code
|
|
# (your puzzle input) of the device. You should be able to fix it, but first
|
|
# you need to be able to run the code in isolation.
|
|
#
|
|
# The boot code is represented as a text file with one instruction per line of
|
|
# text. Each instruction consists of an operation (acc, jmp, or nop) and an
|
|
# argument (a signed number like +4 or -20).
|
|
#
|
|
# acc increases or decreases a single global value called the accumulator by
|
|
# the value given in the argument. For example, acc +7 would increase the
|
|
# accumulator by 7. The accumulator starts at 0. After an acc instruction,
|
|
# the instruction immediately below it is executed next.
|
|
# jmp jumps to a new instruction relative to itself. The next instruction to
|
|
# execute is found using the argument as an offset from the jmp instruction;
|
|
# for example, jmp +2 would skip the next instruction, jmp +1 would
|
|
# continue to the instruction immediately below it, and jmp -20 would
|
|
# cause the instruction 20 lines above to be executed next.
|
|
# nop stands for No OPeration - it does nothing. The instruction immediately
|
|
# below it is executed next.
|
|
#
|
|
# For example, consider the following program:
|
|
#
|
|
# nop +0
|
|
# acc +1
|
|
# jmp +4
|
|
# acc +3
|
|
# jmp -3
|
|
# acc -99
|
|
# acc +1
|
|
# jmp -4
|
|
# acc +6
|
|
#
|
|
# These instructions are visited in this order:
|
|
#
|
|
# nop +0 | 1
|
|
# acc +1 | 2, 8(!)
|
|
# jmp +4 | 3
|
|
# acc +3 | 6
|
|
# jmp -3 | 7
|
|
# acc -99 |
|
|
# acc +1 | 4
|
|
# jmp -4 | 5
|
|
# acc +6 |
|
|
#
|
|
# First, the nop +0 does nothing. Then, the accumulator is increased from
|
|
# 0 to 1 (acc +1) and jmp +4 sets the next instruction to the other acc +1
|
|
# near the bottom. After it increases the accumulator from 1 to 2, jmp -4
|
|
# executes, setting the next instruction to the only acc +3. It sets the
|
|
# accumulator to 5, and jmp -3 causes the program to continue back at the
|
|
# first acc +1.
|
|
#
|
|
# This is an infinite loop: with this sequence of jumps, the program will
|
|
# run forever. The moment the program tries to run any instruction a second
|
|
# time, you know it will never terminate.
|
|
#
|
|
# Immediately before the program would run an instruction a second time, the
|
|
# value in the accumulator is 5.
|
|
#
|
|
# Run your copy of the boot code. Immediately before any instruction is
|
|
# executed a second time, what value is in the accumulator?
|
|
|
|
library(tidyverse)
|
|
|
|
input <- "../input/08-01.txt"
|
|
|
|
read_delim(
|
|
file = input,
|
|
delim = " ",
|
|
col_names = c("instr", "value"),
|
|
col_types = "cd"
|
|
) %>%
|
|
mutate(
|
|
visits = 0
|
|
) -> asm
|
|
|
|
curr <- 1
|
|
accumulator <- 0
|
|
|
|
while (all(asm$visits < 2)) {
|
|
|
|
asm$visits[curr] <- asm$visits[curr] + 1
|
|
|
|
switch(
|
|
asm$instr[curr],
|
|
"nop" = curr + 1,
|
|
"acc" = curr + 1,
|
|
"jmp" = curr + asm[curr,]$value
|
|
) -> nxt
|
|
|
|
if (nxt > nrow(asm)) break
|
|
|
|
if ((asm$visits[curr] < 2) && (asm$instr[curr] == "acc")) {
|
|
accumulator <- accumulator + asm$value[curr]
|
|
}
|
|
|
|
curr <- nxt
|
|
|
|
}
|
|
|
|
# 08-02 -------------------------------------------------------------------
|
|
|
|
read_delim(
|
|
file = input,
|
|
delim = " ",
|
|
col_names = c("instr", "value"),
|
|
col_types = "cd"
|
|
) %>%
|
|
mutate(
|
|
visits = 0
|
|
) -> asm
|
|
|
|
orig_program <- asm
|
|
|
|
for (run in seq_len(nrow(asm))) {
|
|
|
|
asm <- orig_program
|
|
|
|
curr <- 1
|
|
accumulator <- 0
|
|
|
|
switch(
|
|
asm$instr[run],
|
|
"acc" = "acc",
|
|
"nop" = "jmp",
|
|
"jmp" = "nop"
|
|
) -> asm$instr[run]
|
|
|
|
while (all(asm$visits < 2)) {
|
|
|
|
asm$visits[curr] <- asm$visits[curr] + 1
|
|
|
|
switch(
|
|
asm$instr[curr],
|
|
"acc" = curr + 1,
|
|
"nop" = curr + 1,
|
|
"jmp" = curr + asm[curr,]$value
|
|
) -> nxt
|
|
|
|
if (nxt > nrow(asm)) break
|
|
|
|
if ((asm$visits[curr] < 2) && (asm$instr[curr] == "acc")) {
|
|
accumulator <- accumulator + asm$value[curr]
|
|
}
|
|
|
|
curr <- nxt
|
|
|
|
}
|
|
|
|
if (all(asm$visits < 2)) break
|
|
|
|
}
|
|
|
|
accumulator
|
|
|