def run_robot(prog: List[int], start_on_white): white_panels = {(0, 0)} if start_on_white else set() painted_panels = set() location = (0, 0) direction = directions_clockwise[0] m = IntcodeMachine(prog, INSTRUCTIONS) while m.running: try: m.input.append(1 if location in white_panels else 0) while m.step(): pass except EOFError as e: paint = m.output.pop(0) if paint == 0: white_panels -= {location} else: white_panels.add(location) painted_panels.add(location) turn = m.output.pop(0) x = 1 if turn == 1 else -1 direction = directions_clockwise[ (directions_clockwise.index(direction) + x) % 4] location = (location[0] + direction[0], location[1] + direction[1]) return (white_panels, painted_panels)
def test(): def assert_finishes( initial_memory, inpt=[], expected_output=None, expected_memory=None, ): m = IntcodeMachine(initial_memory, INSTRUCTIONS, inpt=list(inpt)) while m.step(): pass if expected_output is not None: assert m.output == expected_output, f"Expected output: {expected_output}, got {m.output}" if expected_memory is not None: assert list(m.memory.values()) == expected_memory golf = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99] assert_finishes(golf, expected_output=golf) m = IntcodeMachine([1102,34915192,34915192,7,4,7,99,0], INSTRUCTIONS) while m.step(): pass assert len(str(m.output[-1])) == 16 assert_finishes([104,1125899906842624,99], expected_output=[1125899906842624]) inp = [12345] assert_finishes([203, 10, 204, 10, 99], inpt=inp, expected_output=inp) assert_finishes([109, 1000, 203, 10, 204, 10, 99], inpt=inp, expected_output=inp) assert_finishes([109, 1000, 203, 10, 4, 1010, 99], inpt=inp, expected_output=inp)
def run(initial_memory: typing.List[int], inpt: typing.List[int], instruction_set): machine = IntcodeMachine(initial_memory, instruction_set, inpt=inpt) while machine.step(): pass other_codes = set(machine.output[:-1]) assert other_codes == {0} or len(other_codes) == 0 return machine.output[-1]
def assert_finishes( initial_memory, inpt=[], expected_output=None, expected_memory=None, ): m = IntcodeMachine(initial_memory, INSTRUCTIONS, inpt=list(inpt)) while m.step(): pass if expected_output is not None: assert m.output == expected_output, f"Expected output: {expected_output}, got {m.output}" if expected_memory is not None: assert list(m.memory.values()) == expected_memory
def assert_finishes(initial_memory, inpt=[], expected_output=None, expected_memory=None, instruction_set=INSTRUCTIONS_P1): def f(): for ele in initial_memory: if issubclass(ele.__class__, IntcodeInstruction): # ele is an Instruction, we should expand it and flatten the result for opcode in ele.expand(): yield opcode else: yield ele m = IntcodeMachine(list(f()), instruction_set, inpt=inpt) while m.step(): pass if expected_output is not None: assert m.output[ -1] == expected_output, f"Expected output: {expected_output}, got {m.output[-1]}" if expected_memory is not None: assert list(m.memory.values()) == expected_memory
def feedback_sequence(program: List[int], settings: Settings): output_vals = set() val = 0 amplifiers: List[IntcodeMachine] = [ IntcodeMachine(program, INSTRUCTIONS, inpt=[s]) for s in settings ] while True: for i in range(len(settings)): try: amplifiers[i].input.append(val) while amplifiers[i].step(): pass val = amplifiers[i].output[-1] except EOFError: val = amplifiers[i].output[-1] if not amplifiers[-1].running: return val if val in output_vals: raise RecursionError("Cycle detected!") # We never ran into this lol else: output_vals.add(val)
def amplifier(program: List[int], input_value: int, setting: int) -> int: m = IntcodeMachine(program, INSTRUCTIONS, inpt=[setting, input_value]) while m.step(): pass return m.output[-1] if len(m.output) > 0 else None
def part(program : List[int], inpt : List[int]): m = IntcodeMachine(program, INSTRUCTIONS, inpt=inpt) while m.step(): pass assert len(m.output) == 1 return m.output[-1]