Advent of Code 2019 - Day 9
Advent of Code 2019 - Day 9
Find my full solution repo here
Debugging this puzzle was a complete nightmare for me. As is the case with most debugging stories, it was completely my fault all along.
The Problem
First, a while back, I thought that the instructions said “a parameter that you write to will always be in immediate mode.” The instructions actually say the exact opposite of that. So, when processing the parameter modes, I would hardcode the parameter mode to “immediate” for arguments that were supposed to be written to. This had some terrible side effects.
The most bad side effect was that this mistake actually led me to get the right answer, because I was handling the writing section of the opcode wrong.
For example, my argument parsing code looked like this:
if immediate mode:
return program[pc + offset]
else:
return program[program[pc + offset]]
My write code: program[arg] = value
And my “read” code just said print(arg)
since the argument parsing code was
supposed to get the right value.
And since I hardcoded “write” parameters to be immediate mode, I was inadvertently doubling up the address calls and getting the right answer in the process.
The Solution
I eventually read every word of the instructions and realized that I had it
backwards. The main thing to come out of this issue was that I added a
write_arg()
method instead of trying to have a single method do both. The two
functions now look like this (with the included relative base):
def get_arg(self, mode, pc_offset):
if mode == 0:
location = self.program[self.pc+pc_offset]
elif mode == 1:
location = self.pc+pc_offset
elif mode == 2:
location = self.program[self.pc+pc_offset] + self.relative_base
return self.program.setdefault(location, 0)
def write_arg(self, mode, pc_offset, value):
if mode == 0:
location = self.program[self.pc+pc_offset]
elif mode == 2:
location = self.program[self.pc+pc_offset] + self.relative_base
self.program[location] = value
It’s also worth noting that I’m now using a dictionary implementation of memory instead of a list due to the extended memory requirement. With this big misstep out of the way, the rest of the puzzle came along quickly. I’m simply tracking the relative base at the instance level and opcode 9 adjusts it as necessary. The code above shows how the relative base affects reading/writing parameters.
The Takeaway
Time and time again, I learn the same lesson when debugging programming issues. That lesson is best described by a quote from Moira, a character in Overwatch:
“When faced with a setback, we must challenge our assumptions.”
Duly noted.
Find my full solution repo here