def num_neighbours(lines: [], line_index: int, pos_index: int, num_lines: int, line_length: int) -> int: '''Check surrounding and current row neighbours of a given position. Does not operate on 2d coords directly, but on index and current versus prev/next lines. ''' total = 0 for ii in range(max(0, line_index - 1), min(num_lines, line_index + 2)): for jj in range(max(0, pos_index - 1), min(line_length, pos_index + 2)): if ii == line_index and jj == pos_index: continue if lines[ii][jj] == '@': total += 1 return total def process_line(lines: []) -> int: '''Iterate through all lines in the map and determine which can be removed this time around''' total = 0 for line_index, line in enumerate(lines): for index, char in enumerate(line): if char == '@': total_neighbours = num_neighbours(lines, line_index, index, len(lines), len(line)) if total_neighbours < 4: total += 1 return total def find_all_accessible_rolls(lines: []) -> int: '''Recursively iterate through removing paper rolls and see how many are opened up for removal after each pass until none can be removed''' total = 0 # Copy the map to note which have been removed without affecting the current checks lines_copy = lines for line_index, line in enumerate(lines): for index, char in enumerate(line): if char == '@': total_neighbours = 0 for ii in range(max(0, line_index - 1), min(len(lines), line_index + 2)): for jj in range(max(0, index - 1), min(len(line), index + 2)): if ii == line_index and jj == index: continue if lines[ii][jj] == '@': total_neighbours += 1 if total_neighbours < 4: total += 1 temp_line = list(lines_copy[line_index]) temp_line[index] = '.' lines_copy[line_index] = ''.join(temp_line) if total != 0: return total + find_all_accessible_rolls(lines_copy) return total def main(): '''Entrypoint''' with open('input.txt', encoding='utf-8') as fh: all_lines = fh.readlines() part1_total = process_line(all_lines) print(f'Part 1: {part1_total}') part2_total = find_all_accessible_rolls(all_lines) print(f'Part 2: {part2_total}') if __name__ == "__main__": main()