from collections import deque from tools.aoc import AOCDay from tools.coordinate import Coordinate from tools.grid import Grid from typing import Any def get_pocket_region(grid: Grid, start: Coordinate, ignore: set) -> set: if grid.get(start): return set() q = deque() q.append(start) p = {start} border_reached = False while q: c = q.pop() if c in ignore or grid.get(c): continue ignore.add(c) n = list(grid.getNeighboursOf(c, includeDefault=True, includeDiagonal=False)) if len(n) < 6: border_reached = True p = set() for nc in n: if grid.get(nc): continue q.append(nc) if not border_reached: p.add(nc) return p def get_pocket_cells(grid: Grid) -> set: p = set() v = set() for x in grid.rangeX(): for y in grid.rangeY(): for z in grid.rangeZ(): c = Coordinate(x, y, z) if c in v: continue p |= get_pocket_region(grid, c, v) return p class Day(AOCDay): inputs = [ [ (64, "input18_test"), (3526, "input18_dennis"), (3326, "input18"), ], [ (58, "input18_test"), (2090, "input18_dennis"), (1996, "input18"), ] ] def get_grid(self) -> Grid: grid = Grid() for line in self.getInput(): grid.set(Coordinate(*map(int, line.split(",")))) return grid def part1(self) -> Any: grid = self.get_grid() side_count = 0 for c in grid.getActiveCells(): side_count += 6 - len(list(grid.getNeighboursOf(c, includeDiagonal=False))) return side_count def part2(self) -> Any: grid = self.get_grid() side_count = 0 p = get_pocket_cells(grid) for c in grid.getActiveCells(): side_count += 6 for n in list(grid.getNeighboursOf(c, includeDiagonal=False, includeDefault=True)): if grid.get(n) or n in p: side_count -= 1 return side_count if __name__ == '__main__': day = Day(2022, 18) day.run(verbose=True)