from operator import add, mul, eq, lt import enum @enum.unique class State(enum.Enum): """Execution state class.""" CONTINUE = 0 HALT = 1 WAIT = 2 class Opcode: def __init__(self, func, parnum): self.parnum = parnum self.run = func def operation(operator): """Make opcode from operator.""" def opcode(state, p1, p2, p3): state.memory.write(p3, operator(state.memory.read(p1), state.memory.read(p2))) state.i += 4 return State.CONTINUE return Opcode(opcode, 3) def jump(flag): def opcode(state, p1, p2): state.i = state.memory.read(p2) if (state.memory.read(p1) > 0)==flag else state.i+3 return State.CONTINUE return Opcode(opcode, 2) def adjust_base(state, p1): state.rel_base += state.memory.read(p1) state.i += 2 return State.CONTINUE def input(state, p1): if state.IO.wait_for_input(): return State.WAIT state.memory.write(p1, state.IO.input()) state.i += 2 return State.CONTINUE def output(state, p1): state.IO.output(state.memory.read(p1)) state.i += 2 return State.CONTINUE op_add = operation(add) op_mul = operation(mul) op_lt = operation(lt) op_eq = operation(eq) op_jump_if_true = jump(True) op_jump_if_false = jump(False) op_adjust_relative_base = Opcode(adjust_base, 1) op_input = Opcode(input, 1) op_output = Opcode(output, 1) op_halt = Opcode(lambda x: State.HALT, 0) opcodes = {1 : op_add, 2 : op_mul, 3 : op_input, 4 : op_output, 5 : op_jump_if_true, 6 : op_jump_if_false, 7 : op_lt, 8 : op_eq, 9 : op_adjust_relative_base, 99 : op_halt} def parse_op(op): op = str(op) par_modes, op = op[:-2][::-1], int(op[-2:]) par_modes = par_modes + '0'*(opcodes[op].parnum - len(par_modes)) return op, map(int, par_modes) def run_op(state): op, par_modes = parse_op(state.memory.read(state.i)) pars = [] for pn, mode in enumerate(par_modes, start=1): p = state.i + pn if mode == 0: p = state.memory.read(p) elif mode == 2: p = state.rel_base + state.memory.read(p) pars.append(p) return opcodes[op].run(state, *pars)