This commit is contained in:
Dece 2019-12-09 23:03:48 +01:00
parent 037abe5c4a
commit e6a4d314d7
2 changed files with 33 additions and 31 deletions

View file

@ -9,9 +9,15 @@ EX3 = "104,1125899906842624,99"
def main(): def main():
with open("day9.txt", "rt") as input_file: with open("day9.txt", "rt") as input_file:
text = input_file.readlines()[0].rstrip() text = input_file.readlines()[0].rstrip()
codes = Intcode.parse_input(text) codes = Intcode.parse_input(text)
# Part 1
Intcode(codes, print_output=True).run([1]) Intcode(codes, print_output=True).run([1])
# Part 2
Intcode(codes, print_output=True).run([2])
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -25,7 +25,7 @@ class PMode(IntEnum):
class Intcode(object): class Intcode(object):
def __init__(self, program, print_output=False): def __init__(self, program, print_output=False, debug=False):
self._memory = program.copy() self._memory = program.copy()
self.ip = 0 self.ip = 0
self.rel_base = 0 self.rel_base = 0
@ -35,23 +35,22 @@ class Intcode(object):
self.halt = False self.halt = False
self.outputs = [] self.outputs = []
self.print_output = print_output self.print_output = print_output
self.debug = debug
@staticmethod @staticmethod
def parse_input(text): def parse_input(text):
return [int(i) for i in text.rstrip().split(",")] return [int(i) for i in text.rstrip().split(",")]
def log(self, message, *args):
if self.debug:
print("debug:", message, *args)
def run(self, inputs=None): def run(self, inputs=None):
self.inputs = inputs or [] self.inputs = inputs or []
handlers = self.get_handlers() handlers = self.get_handlers()
while not self.halt: while not self.halt:
self.read_code() self.read_code()
handler = handlers.get(self.ctx_op) handlers.get(self.ctx_op)()
if not handler:
sys.exit("Wrong opcode: {}".format(self.ctx_op))
try:
handler()
except Exception as exc:
sys.exit("Exception: {}".format(exc))
return self.outputs[-1] if self.outputs else 0 return self.outputs[-1] if self.outputs else 0
def get_handlers(self): def get_handlers(self):
@ -78,48 +77,45 @@ class Intcode(object):
def _check_memory_limits(self, index): def _check_memory_limits(self, index):
if index >= len(self._memory): if index >= len(self._memory):
self._extend_memory(index + 1) new_size = index + 1
self._memory += [0] * (new_size - len(self._memory))
def _extend_memory(self, new_size):
if len(self._memory) >= new_size:
return
self._memory += [0] * (new_size - len(self._memory))
def read_code(self): def read_code(self):
code = self.mem_get(self.ip) raw_code = self.mem_get(self.ip)
self.ctx_op = code % 100 code = raw_code % 100
code //= 100 self.ctx_op = Op(code)
code = raw_code // 100
self.ctx_modes = [] self.ctx_modes = []
for _ in range(0, 3): for _ in range(0, 3):
self.ctx_modes.append(PMode(code % 10)) self.ctx_modes.append(PMode(code % 10))
code //= 10 code //= 10
self.log("read_code", raw_code, self.ctx_op, self.ctx_modes)
def param(self, index): def param(self, index, pointer=False):
mode = self.ctx_modes[index - 1] mode = self.ctx_modes[index - 1]
if mode == PMode.POS: if mode == PMode.POS:
address = self.mem_get(self.ip + index) address = self.mem_get(self.ip + index)
return self.mem_get(address) return address if pointer else self.mem_get(address)
elif mode == PMode.IMM: elif mode == PMode.IMM:
return self.mem_get(self.ip + index) return self.mem_get(self.ip + index)
elif mode == PMode.REL: elif mode == PMode.REL:
relative_jump = self.mem_get(self.ip + index) address = self.rel_base + self.mem_get(self.ip + index)
address = self.rel_base + relative_jump return address if pointer else self.mem_get(address)
return self.mem_get(address)
def write_pos_ofs(self, pos_offset, value):
output_pos = self.mem_get(self.ip + pos_offset)
self.mem_set(output_pos, value)
def write_at_param(self, param_offset, value):
self.mem_set(self.param(param_offset, pointer=True), value)
def op_add(self): def op_add(self):
self.write_pos_ofs(3, self.param(1) + self.param(2)) self.write_at_param(3, self.param(1) + self.param(2))
self.ip += 4 self.ip += 4
def op_mul(self): def op_mul(self):
self.write_pos_ofs(3, self.param(1) * self.param(2)) self.write_at_param(3, self.param(1) * self.param(2))
self.ip += 4 self.ip += 4
def op_in(self): def op_in(self):
self.write_pos_ofs(1, self.inputs.pop(0)) self.mem_set(self.param(1, pointer=True), self.inputs.pop(0))
self.ip += 2 self.ip += 2
def op_out(self): def op_out(self):
@ -141,11 +137,11 @@ class Intcode(object):
self.ip += 3 self.ip += 3
def op_lt(self): def op_lt(self):
self.write_pos_ofs(3, int(self.param(1) < self.param(2))) self.write_at_param(3, int(self.param(1) < self.param(2)))
self.ip += 4 self.ip += 4
def op_eq(self): def op_eq(self):
self.write_pos_ofs(3, int(self.param(1) == self.param(2))) self.write_at_param(3, int(self.param(1) == self.param(2)))
self.ip += 4 self.ip += 4
def op_srb(self): def op_srb(self):