def __init__(self, input=NoneInput(), output=VoidOutput()): self._input = input self._output = output self._memory = Memory() self._parameter_factory = ParameterFactory(self._memory) self._operation_factory = OperationFactory(self._memory, self._input, self._output)
class IntcodeComputer: def __init__(self, input=NoneInput(), output=VoidOutput()): self._input = input self._output = output self._memory = Memory() self._parameter_factory = ParameterFactory(self._memory) self._operation_factory = OperationFactory(self._memory, self._input, self._output) def reset_memory(self, data=[]): self._memory.reset(data) def write_memory(self, data): self._memory.insert(data) def execute_instruction(self, instruction_pointer): instruction_code = self._memory[instruction_pointer] instruction_digits = [int(digit) for digit in str(instruction_code)] opcode = instruction_digits.pop() if instruction_digits: opcode += instruction_digits.pop() * 10 operation = self._operation_factory.create_operation(opcode) parameters = self._parameter_factory.create_parameters( instruction_digits, operation.parameter_count, instruction_pointer) operation.execute(parameters, self._input, self._output) return operation.get_new_pointer(instruction_pointer) def run_program(self): instruction_pointer = 0 while not instruction_pointer == -1: instruction_pointer = self.execute_instruction(instruction_pointer)
def test_get_immediate_parameter(self): memory = Memory([2, 4, 15, 12]) pointer = 2 parameter = ImmediateParameter(memory, pointer) value = parameter.get() self.assertEqual(15, value)
def test_set_position_parameter(self): memory = Memory([2, 3, 15, 12]) pointer = 0 parameter = PositionParameter(memory, pointer) parameter.set(73) self.assertEqual(73, memory[2])
def test_get_position_parameter(self): memory = Memory([2, 3, 15, 12]) pointer = 1 parameter = PositionParameter(memory, pointer) value = parameter.get() self.assertEqual(12, value)
def test_set_immediate_parameter(self): memory = Memory([2, 4, 15, 12]) pointer = 1 parameter = ImmediateParameter(memory, pointer) parameter.set(57) self.assertEqual(57, memory[1])
def test_creates_position_parameter(self): memory = Memory() factory = ParameterFactory(memory) pointer = 7 parameter = factory.create_parameter(0, pointer) self.assertTrue(isinstance(parameter, PositionParameter)) self.assertEqual(memory, parameter._memory) self.assertEqual(pointer, parameter._pointer)
def test_creates_immediate_parameter(self): memory = Memory() factory = ParameterFactory(memory) pointer = 3 parameter = factory.create_parameter(1, pointer) self.assertTrue(isinstance(parameter, ImmediateParameter)) self.assertEqual(memory, parameter._memory) self.assertEqual(pointer, parameter._pointer)
class OperationsTests(unittest.TestCase): _memory = Memory() _input = NoneInput() _output = LastOutput() _operation_factory = OperationFactory(_memory, _input, _output) def test_add_operation(self): parameters = [MockParameter(11), MockParameter(7), MockParameter(0)] operation = self._operation_factory.create_operation(OperationCode.ADD) operation.execute(parameters, None, None) self.assertEqual(None, parameters[0].set_value) self.assertEqual(None, parameters[1].set_value) self.assertEqual(18, parameters[2].set_value) def test_add_advances_pointer(self): operation = self._operation_factory.create_operation(OperationCode.ADD) self.assertEqual(7, operation.get_new_pointer(3)) def test_multiply_operation(self): parameters = [MockParameter(11), MockParameter(7), MockParameter(0)] operation = self._operation_factory.create_operation( OperationCode.MULTIPLY) operation.execute(parameters, None, None) self.assertEqual(None, parameters[0].set_value) self.assertEqual(None, parameters[1].set_value) self.assertEqual(77, parameters[2].set_value) def test_multiply_advances_pointer(self): operation = self._operation_factory.create_operation( OperationCode.MULTIPLY) self.assertEqual(7, operation.get_new_pointer(3)) def test_input_operation(self): parameters = [MockParameter(4)] input = SingleInput(17) operation = self._operation_factory.create_operation( OperationCode.INPUT) operation.execute(parameters, input, None) self.assertEqual(17, parameters[0].set_value) def test_input_advances_pointer(self): operation = self._operation_factory.create_operation( OperationCode.INPUT) self.assertEqual(5, operation.get_new_pointer(3)) def test_output_operation(self): parameters = [MockParameter(7)] output = LastOutput() operation = self._operation_factory.create_operation( OperationCode.OUTPUT) operation.execute(parameters, None, output) self.assertEqual(7, output) def test_output_advances_pointer(self): operation = self._operation_factory.create_operation( OperationCode.OUTPUT) self.assertEqual(5, operation.get_new_pointer(3)) def test_jump_if_true_jumps(self): parameters = [MockParameter(17), MockParameter(39)] operation = self._operation_factory.create_operation( OperationCode.JUMP_IF_TRUE) operation.execute(parameters, None, None) self.assertEqual(39, operation.get_new_pointer(9)) def test_jump_if_true_doesnt(self): parameters = [MockParameter(0), MockParameter(39)] operation = self._operation_factory.create_operation( OperationCode.JUMP_IF_TRUE) operation.execute(parameters, None, None) self.assertEqual(12, operation.get_new_pointer(9)) def test_jump_if_false_jumps(self): parameters = [MockParameter(0), MockParameter(39)] operation = self._operation_factory.create_operation( OperationCode.JUMP_IF_FALSE) operation.execute(parameters, None, None) self.assertEqual(39, operation.get_new_pointer(9)) def test_jump_if_false_doesnt(self): parameters = [MockParameter(17), MockParameter(39)] operation = self._operation_factory.create_operation( OperationCode.JUMP_IF_FALSE) operation.execute(parameters, None, None) self.assertEqual(12, operation.get_new_pointer(9)) def test_less_than_operation(self): parameters = [ MockParameter(231), MockParameter(11232), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.LESS_THAN) operation.execute(parameters, None, None) self.assertEqual(1, parameters[2].set_value) def test_less_than_operation_if_equal(self): parameters = [ MockParameter(231), MockParameter(231), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.LESS_THAN) operation.execute(parameters, None, None) self.assertEqual(0, parameters[2].set_value) def test_less_than_operation_if_greater(self): parameters = [ MockParameter(1231), MockParameter(231), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.LESS_THAN) operation.execute(parameters, None, None) self.assertEqual(0, parameters[2].set_value) def test_less_than_advances_pointer(self): operation = self._operation_factory.create_operation( OperationCode.LESS_THAN) self.assertEqual(17, operation.get_new_pointer(13)) def test_equals_operation(self): parameters = [ MockParameter(231), MockParameter(231), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.EQUALS) operation.execute(parameters, None, None) self.assertEqual(1, parameters[2].set_value) def test_equals_operation_if_less(self): parameters = [ MockParameter(231), MockParameter(2315), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.EQUALS) operation.execute(parameters, None, None) self.assertEqual(0, parameters[2].set_value) def test_equals_operation_if_greater(self): parameters = [ MockParameter(1231), MockParameter(231), MockParameter(23) ] operation = self._operation_factory.create_operation( OperationCode.EQUALS) operation.execute(parameters, None, None) self.assertEqual(0, parameters[2].set_value) def test_equals_advances_pointer(self): operation = self._operation_factory.create_operation( OperationCode.EQUALS) self.assertEqual(17, operation.get_new_pointer(13)) def test_halt_operation(self): parameters = [MockParameter(11), MockParameter(7), MockParameter(0)] operation = self._operation_factory.create_operation(OperationCode.END) operation.execute(parameters, None, None) self.assertEqual(None, parameters[0].set_value) self.assertEqual(None, parameters[1].set_value) self.assertEqual(None, parameters[2].set_value)