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
|