138 lines
6.4 KiB
Plaintext
138 lines
6.4 KiB
Plaintext
Advent of Code
|
||
|
||
--- Day 19: Go With The Flow ---
|
||
|
||
With the Elves well on their way constructing the North Pole base, you turn
|
||
your attention back to understanding the inner workings of programming the
|
||
device.
|
||
|
||
You can't help but notice that the device's opcodes don't contain any flow
|
||
control like jump instructions. The device's manual goes on to explain:
|
||
|
||
"In programs where flow control is required, the instruction pointer can be
|
||
bound to a register so that it can be manipulated directly. This way,
|
||
setr/seti can function as absolute jumps, addr/addi can function as relative
|
||
jumps, and other opcodes can cause truly fascinating effects."
|
||
|
||
This mechanism is achieved through a declaration like #ip 1, which would
|
||
modify register 1 so that accesses to it let the program indirectly access the
|
||
instruction pointer itself. To compensate for this kind of binding, there are
|
||
now six registers (numbered 0 through 5); the five not bound to the
|
||
instruction pointer behave as normal. Otherwise, the same rules apply as the
|
||
last time you worked with this device.
|
||
|
||
When the instruction pointer is bound to a register, its value is written to
|
||
that register just before each instruction is executed, and the value of that
|
||
register is written back to the instruction pointer immediately after each
|
||
instruction finishes execution. Afterward, move to the next instruction by
|
||
adding one to the instruction pointer, even if the value in the instruction
|
||
pointer was just updated by an instruction. (Because of this, instructions
|
||
must effectively set the instruction pointer to the instruction before the one
|
||
they want executed next.)
|
||
|
||
The instruction pointer is 0 during the first instruction, 1 during the
|
||
second, and so on. If the instruction pointer ever causes the device to
|
||
attempt to load an instruction outside the instructions defined in the
|
||
program, the program instead immediately halts. The instruction pointer starts
|
||
at 0.
|
||
|
||
It turns out that this new information is already proving useful: the CPU in
|
||
the device is not very powerful, and a background process is occupying most of
|
||
its time. You dump the background process' declarations and instructions to a
|
||
file (your puzzle input), making sure to use the names of the opcodes rather
|
||
than the numbers.
|
||
|
||
For example, suppose you have the following program:
|
||
|
||
#ip 0
|
||
seti 5 0 1
|
||
seti 6 0 2
|
||
addi 0 1 0
|
||
addr 1 2 3
|
||
setr 1 0 0
|
||
seti 8 0 4
|
||
seti 9 0 5
|
||
|
||
When executed, the following instructions are executed. Each line contains the
|
||
value of the instruction pointer at the time the instruction started, the
|
||
values of the six registers before executing the instructions (in square
|
||
brackets), the instruction itself, and the values of the six registers after
|
||
executing the instruction (also in square brackets).
|
||
|
||
ip=0 [0, 0, 0, 0, 0, 0] seti 5 0 1 [0, 5, 0, 0, 0, 0]
|
||
ip=1 [1, 5, 0, 0, 0, 0] seti 6 0 2 [1, 5, 6, 0, 0, 0]
|
||
ip=2 [2, 5, 6, 0, 0, 0] addi 0 1 0 [3, 5, 6, 0, 0, 0]
|
||
ip=4 [4, 5, 6, 0, 0, 0] setr 1 0 0 [5, 5, 6, 0, 0, 0]
|
||
ip=6 [6, 5, 6, 0, 0, 0] seti 9 0 5 [6, 5, 6, 0, 0, 9]
|
||
|
||
In detail, when running this program, the following events occur:
|
||
|
||
• The first line (#ip 0) indicates that the instruction pointer should be
|
||
bound to register 0 in this program. This is not an instruction, and so
|
||
the value of the instruction pointer does not change during the processing
|
||
of this line.
|
||
• The instruction pointer contains 0, and so the first instruction is
|
||
executed (seti 5 0 1). It updates register 0 to the current instruction
|
||
pointer value (0), sets register 1 to 5, sets the instruction pointer to
|
||
the value of register 0 (which has no effect, as the instruction did not
|
||
modify register 0), and then adds one to the instruction pointer.
|
||
• The instruction pointer contains 1, and so the second instruction, seti 6
|
||
0 2, is executed. This is very similar to the instruction before it: 6 is
|
||
stored in register 2, and the instruction pointer is left with the value
|
||
2.
|
||
• The instruction pointer is 2, which points at the instruction addi 0 1 0.
|
||
This is like a relative jump: the value of the instruction pointer, 2, is
|
||
loaded into register 0. Then, addi finds the result of adding the value in
|
||
register 0 and the value 1, storing the result, 3, back in register 0.
|
||
Register 0 is then copied back to the instruction pointer, which will
|
||
cause it to end up 1 larger than it would have otherwise and skip the next
|
||
instruction (addr 1 2 3) entirely. Finally, 1 is added to the instruction
|
||
pointer.
|
||
• The instruction pointer is 4, so the instruction setr 1 0 0 is run. This
|
||
is like an absolute jump: it copies the value contained in register 1, 5,
|
||
into register 0, which causes it to end up in the instruction pointer. The
|
||
instruction pointer is then incremented, leaving it at 6.
|
||
• The instruction pointer is 6, so the instruction seti 9 0 5 stores 9 into
|
||
register 5. The instruction pointer is incremented, causing it to point
|
||
outside the program, and so the program ends.
|
||
|
||
What value is left in register 0 when the background process halts?
|
||
|
||
Your puzzle answer was 888.
|
||
|
||
--- Part Two ---
|
||
|
||
A new background process immediately spins up in its place. It appears
|
||
identical, but on closer inspection, you notice that this time, register 0
|
||
started with the value 1.
|
||
|
||
What value is left in register 0 when this new background process halts?
|
||
|
||
Your puzzle answer was 10708992.
|
||
|
||
Both parts of this puzzle are complete! They provide two gold stars: **
|
||
|
||
References
|
||
|
||
Visible links
|
||
. https://adventofcode.com/
|
||
. https://adventofcode.com/2018/about
|
||
. https://adventofcode.com/2018/events
|
||
. https://adventofcode.com/2018/settings
|
||
. https://adventofcode.com/2018/auth/logout
|
||
. Advent of Code Supporter
|
||
https://adventofcode.com/2018/support
|
||
. https://adventofcode.com/2018
|
||
. https://adventofcode.com/2018
|
||
. https://adventofcode.com/2018/support
|
||
. https://adventofcode.com/2018/sponsors
|
||
. https://adventofcode.com/2018/leaderboard
|
||
. https://adventofcode.com/2018/stats
|
||
. https://adventofcode.com/2018/sponsors
|
||
. https://adventofcode.com/2018/day/16
|
||
. https://adventofcode.com/2018/day/16
|
||
. https://en.wikipedia.org/wiki/Program_counter
|
||
. https://adventofcode.com/2018/day/16
|
||
. https://adventofcode.com/2018
|
||
. https://adventofcode.com/2018/day/19/input
|