def run(self):
    self.output = None
    while (self.instruction_ptr < len(self.memory)):
        (param_mode, opcode) = self.parse_opcode()
        if (opcode == self.OP_HALT):
            return 0
        elif (opcode == self.OP_ADD):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            self.set_paramater(param_mode[2], (in1 + in2))
        elif (opcode == self.OP_MULTIPLY):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            self.set_paramater(param_mode[2], (in1 * in2))
        elif (opcode == self.OP_INPUT):
            if self.inputs:
                self.last_input = self.inputs.pop()
            if (self.last_input != None):
                self.set_paramater(param_mode[0], self.last_input)
            else:
                raise Exception(f'{self.last_input} is not a valid input')
        elif (opcode == self.OP_OUTPUT):
            self.output = self.get_paramater(param_mode[0])
            return 1
        elif (opcode == self.OP_JUMP_TRUE):
            do_jump = self.get_paramater(param_mode[0])
            new_addr = self.get_paramater(param_mode[1])
            if (do_jump != 0):
                self.instruction_ptr = new_addr
        elif (opcode == self.OP_JUMP_FALSE):
            do_jump = self.get_paramater(param_mode[0])
            new_addr = self.get_paramater(param_mode[1])
            if (do_jump == 0):
                self.instruction_ptr = new_addr
        elif (opcode == self.OP_LESS_THAN):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            if (in1 < in2):
                self.set_paramater(param_mode[2], 1)
            else:
                self.set_paramater(param_mode[2], 0)
        elif (opcode == self.OP_EQUALS):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            if (in1 == in2):
                self.set_paramater(param_mode[2], 1)
            else:
                self.set_paramater(param_mode[2], 0)
        elif (opcode == self.OP_MOD_REL):
            val = self.get_paramater(param_mode[0])
            self.relative_base += val
        else:
            raise Exception(f'Unknown opcode {opcode} at addr {self.instruction_ptr}.')
            self.reset()
    return (- 1)
def run(self):
    self.output = None
    while (self.instruction_ptr < len(self.memory)):
        (param_mode, opcode) = self.parse_opcode()
        if (opcode == self.OP_HALT):
            return 0
        elif (opcode == self.OP_ADD):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            self.set_paramater(param_mode[2], (in1 + in2))
        elif (opcode == self.OP_MULTIPLY):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            self.set_paramater(param_mode[2], (in1 * in2))
        elif (opcode == self.OP_INPUT):
            if self.inputs:
                self.last_input = self.inputs.pop()
            if (self.last_input != None):
                self.set_paramater(param_mode[0], self.last_input)
            else:
                raise Exception(f'{self.last_input} is not a valid input')
        elif (opcode == self.OP_OUTPUT):
            self.output = self.get_paramater(param_mode[0])
            return 1
        elif (opcode == self.OP_JUMP_TRUE):
            do_jump = self.get_paramater(param_mode[0])
            new_addr = self.get_paramater(param_mode[1])
            if (do_jump != 0):
                self.instruction_ptr = new_addr
        elif (opcode == self.OP_JUMP_FALSE):
            do_jump = self.get_paramater(param_mode[0])
            new_addr = self.get_paramater(param_mode[1])
            if (do_jump == 0):
                self.instruction_ptr = new_addr
        elif (opcode == self.OP_LESS_THAN):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            if (in1 < in2):
                self.set_paramater(param_mode[2], 1)
            else:
                self.set_paramater(param_mode[2], 0)
        elif (opcode == self.OP_EQUALS):
            in1 = self.get_paramater(param_mode[0])
            in2 = self.get_paramater(param_mode[1])
            if (in1 == in2):
                self.set_paramater(param_mode[2], 1)
            else:
                self.set_paramater(param_mode[2], 0)
        elif (opcode == self.OP_MOD_REL):
            val = self.get_paramater(param_mode[0])
            self.relative_base += val
        else:
            raise Exception(f'Unknown opcode {opcode} at addr {self.instruction_ptr}.')
            self.reset()
    return (- 1)