def play(program, fps=0): # type: (NewProgram, int) -> int ''' Play the game until it ends ''' program[0] = 2 pointer = 0 relative_base = 0 input = [] game_map = None while pointer != -1: program, output, pointer, relative_base = run_program( program, input, pointer, True, relative_base) game_map = update_game_map(output, game_map) if fps: print_game_map(game_map) sleep(1 / fps) paddle_pos = find_object(game_map, 3) ball_pos = find_object(game_map, 4) if (ball_pos is None or paddle_pos is None): input = [0] continue input = [(ball_pos.x > paddle_pos.x) - (ball_pos.x < paddle_pos.x)] if fps: print_game_map(update_game_map(output, game_map)) return game_map[Point(-1, 0)]
def paint(program, start_color): # type: (NewProgram, int) -> Tuple[int, PaintedArea] ''' Run a painting program on the robot ''' directions = [Direction(0, -1), Direction(1, 0), Direction(0, 1), Direction(-1, 0)] painted_area = defaultdict(lambda: defaultdict(lambda: -1)) painted_area[0][0] = start_color position = Point(0, 0) direction = 0 pointer = 0 relative_base = 0 while pointer != -1: current_color = max(painted_area[position.y][position.x], 0) program, output, pointer, relative_base = run_program(program, [current_color], pointer, True, relative_base) painted_area[position.y][position.x] = output[0] if output[1] == 1: direction = (direction + 1) % len(directions) else: direction = (direction - 1) % len(directions) position.x = position.x + directions[direction].x position.y = position.y + directions[direction].y nb_painted = 0 for y in painted_area: for x in painted_area[y]: if painted_area[y][x] > -1: nb_painted += 1 return nb_painted, painted_area
def count_tiles(program, tile_type): # type: (NewProgram, int) -> int ''' Count the number of tiles of a given type. ''' _, output, _, _ = run_program(program) count = 0 for i in range(0, len(output) // 3): if output[3 * i + 2] == tile_type: count += 1 return count
def run(with_tests = True): with open(os.path.dirname(__file__) + os.sep + 'input.txt', 'r') as in_file: program = ast.literal_eval('[' + in_file.read().strip() + ']') checks_d17p1() _, output, _, _ = run_program(program) system_map, vacuum_state = build_map(output) d17p1 = sum_alignement_parameters(find_intersections(system_map)) print(f'Day 17, Part 1 : {d17p1}') # 8928 checks_d17p2() instructions = generate_instructions(system_map, vacuum_state) d17p2 = move_robot(program, instructions) print(f'Day 17, Part 2 : {d17p2}') # 880360
def build_map(program): # type: (Program) -> Tuple[SectionMap, SectionMap, Point] ''' Builds the section map by keeping the wall to the right ''' section_map = defaultdict(lambda: -2, {Point(0, 0): 3}) distance_map = defaultdict(lambda: sys.maxsize, {Point(0, 0): 0}) pointer = 0 relative_base = 0 direction = 1 position = Point(0, 0) oxygen_system_location = None while pointer != -1: program, output, pointer, relative_base = run_program( program, [direction + 1], pointer, True, relative_base) result = output[0] if result == 0: section_map[position + directions[direction]] = -1 # Droid hit a wall, change the direction to keep the wall on the right direction = next_direction[direction] else: position += directions[direction] section_map[position] = max(section_map[position], result) distance_map[position] = min( [distance_map[position + directions[i]] for i in range(0, 4)]) + 1 if result == 2: oxygen_system_location = position # Droid didn't hit a wall, go back to the previous direction to keep the wall on the right direction = next_direction.index(direction) # Back to the start and all direction from the start are known, the map is completed if position == Point(0, 0) and section_map[directions[ 0]] != -2 and section_map[directions[1]] != -2 and section_map[ directions[2]] != -2 and section_map[directions[3]] != -2: break return section_map, distance_map, oxygen_system_location
def move_robot(program, instructions): # type: (Program, Text) -> int ''' Moves the robot and return the amount of collected dust ''' main_routine, functions = compress_instructions(instructions) # Found by hand... main_routine = "A,B,A,B,A,C,B,C,A,C" functions = {'A': 'L,6,R,12,L,6', 'B': 'R,12,L,10,L,4,L,6', 'C':'L,10,L,10,L,4,L,6'} input = list(map(ord, main_routine)) input.append(10) for function in functions.values(): input.extend(map(ord, function)) input.append(10) input.append(ord('n')) input.append(10) program[0] = 2 _, output, _, _ = run_program(program, input) return output[-1]
def get_status(x, y, program): _, output, _, _ = run_program(program, [x, y]) return output[0] == 1