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
 |