def test_16d(self): code = '1102,34915192,34915192,7,4,7,99,0' program = Program(code) output = StringIO() standalone(program, '', output) # should output 16 digit number self.assertEqual(len(output.read().rstrip()), 16)
def test_largenum(self): code = '104,1125899906842624,99' program = Program(code) output = StringIO() standalone(program, '', output) # should output the large number from code[1] self.assertEqual(output.read().rstrip(), code.split(',')[1])
def test_quine(self): code = '109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99' program = Program(code, rw=False) output = StringIO() # no rewind output every call to read it in full at the end standalone(program, '', output) quine = ','.join(output.read().rstrip().split('\n')) # Program should output a copy of itself self.assertEqual(quine, code)
def evaluate_amplifiers(program, min_phase=0, max_phase=4): max_signal = 0 max_phase_sequence = None phase_sequences = permutations(range(min_phase, max_phase + 1)) for sequence in phase_sequences: orig_sequence = sequence logging.info(f"Processing {sequence=}") signal = 0 amplifiers = [] for i in range(len(sequence) + 1): code_copy = program.code.copy() program_copy = Program(code_copy) amplifiers.append(program_copy) if min_phase > 4: # feedback loop mode sequence = cycle(enumerate(sequence)) else: sequence = enumerate(sequence) for i, (amplifier, phase) in enumerate(sequence): logging.info("*" * 12 + f" Amplifier {chr(amplifier+65)}\n") if i < 5: # init with phase logging.info(f"{phase=}") logging.info(f"Input: {phase=}, {signal=}") initial_input = f"{phase}\n{signal}" else: logging.info(f"Input {signal=}") initial_input = f"{signal}" out = StringIO() # resume the amplifier at its last pc standalone(amplifiers[amplifier], initial_input, out) output = out.read().rstrip() logging.info(f"{output=}") out_match = re.search('(\d+)', output) if out_match: (signal, ) = out_match.groups() logging.info(f"{signal=}") else: break if int(signal) > max_signal: max_signal = int(signal) max_phase_sequence = list(orig_sequence) logging.info(f"{max_phase_sequence=}") logging.info(f"{max_signal=}") return max_signal
def move(self, d): direction = Direction(d) inp = f"{direction.value}" out = StringIO() logger.debug(f"Moving {direction.name}") standalone(self.program, inp, out) status = self.Status(int(out.read().rstrip())) logger.debug(f"({status.name})") if status in [self.Status.MOVED, self.Status.FOUND]: self.location.update(direction) return status
def test_eq_imm(self): code = '3,3,1108,-1,8,3,4,3,99' program = Program(code) # output is 1 if input equals 8 else 0 output = StringIO() standalone(program, '8', output) self.assertEqual(output.read().rstrip(), '1') program = Program(code) output = StringIO() standalone(program, '88', output) self.assertEqual(output.read().rstrip(), '0')
def test_lt_pos(self): code = '3,9,7,9,10,9,4,9,99,-1,8' program = Program(code) # output is 1 if input is less than 8 else 0 output = StringIO() standalone(program, '7', output) self.assertEqual(output.read().rstrip(), '1') program = Program(code) output = StringIO() standalone(program, '9', output) self.assertEqual(output.read().rstrip(), '0')
def test_jmp_imm(self): code = '3,3,1105,-1,9,1101,0,0,12,4,12,99,1' program = Program(code) # output 0 if input is zero else 1 output = StringIO() standalone(program, '0', output) self.assertEqual(output.read().rstrip(), '0') program = Program(code) output = StringIO() standalone(program, '2', output) self.assertEqual(output.read().rstrip(), '1')
def test_jmp_pos(self): code = '3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9' program = Program(code) # output 0 if input is zero else 1 output = StringIO() standalone(program, '0', output) self.assertEqual(output.read().rstrip(), '0') program = Program(code) output = StringIO() standalone(program, '2', output) self.assertEqual(output.read().rstrip(), '1')
def test_lt_imm(self): code = '3,3,1107,-1,8,3,4,3,99' program = Program(code) # output is 1 if input is less than 8 else 0 output = StringIO() standalone(program, '1', output) self.assertEqual(output.read().rstrip(), '1') program = Program(code) output = StringIO() standalone(program, '9', output) self.assertEqual(output.read().rstrip(), '0')
def hull_painting(program, starting_color = 0): program.rewind_output = False panels_painted = {} current_panel = Loc(0,0) panels_painted[current_panel] = starting_color current_direction = UP # store sizes for rendering largest_x = 0 largest_y = 0 smallest_x = 0 smallest_y = 0 while True: # all panels black(0) by default camera = panels_painted.get(current_panel, 0) out = StringIO() inp = f"{camera}" # Run intcode, it'll suspend on input standalone(program, inp, out) output = out.read().rstrip().split("\n") if output[0]: (color,) = re.search('(\d+)', output[0]).groups() color = int(color) (turn,) = re.search('(\d+)', output[1]).groups() turn = int(turn) panels_painted[current_panel] = color logging.debug(f"Painted {current_panel} {COLORS[color]}") (current_panel, current_direction) = get_movement(current_panel, current_direction, turn) curr_x = current_panel.x curr_y = current_panel.y if curr_x > largest_x: largest_x = curr_x if curr_y > largest_y: largest_y = curr_y if curr_x < smallest_x: smallest_x = curr_x if curr_y < smallest_y: smallest_y = curr_y logging.debug(f"Turned {DIRECTIONS[current_direction]}") else: # halted break map_x = largest_x + abs(smallest_x) map_y = largest_y + abs(smallest_y) return (panels_painted, map_x, map_y)
def run_game(program, screen): # play for free program.code[0] = 2 inp = "0" while True: out = StringIO() old_stdout = sys.stdout standalone(program, inp, out) (pad, ball) = update_screen(screen, out.read().split('\n')) sys.stdout = old_stdout render_game(screen) if ball is None: break # Make pad follow the ball, to play automatically if ball > pad: inp = "1" elif ball < pad: inp = "-1" else: inp = "0"
def test_lt_qe_gt(self): code = ('3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,' '1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,' '999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99') # 999 if value < 8 program = Program(code) output = StringIO() standalone(program, '0', output) self.assertEqual(output.read().rstrip(), '999') # 1000 if value == 8 program = Program(code) output = StringIO() standalone(program, '8', output) self.assertEqual(output.read().rstrip(), '1000') # 1001 if value > 8 program = Program(code) output = StringIO() standalone(program, '80', output) self.assertEqual(output.read().rstrip(), '1001')
def init_game(program): out = StringIO() standalone(program, '', out) screen = {} update_screen(screen, out.read().split('\n')) return screen
def test_phase2(self): with open(f'{self.input_loc}/day9') as inp: program = Program(inp.read()) output = StringIO() standalone(program, '2', output) self.assertEqual(output.read().rstrip(), '58534')