from queue import PriorityQueue droplet = {tuple(map(int,line.split(","))) for line in open("18.input")} NBRS = [ (1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0,-1), ] def add(a, b): return (a[0] + b[0], a[1] + b[1], a[2] + b[2]) def nbr_cnt(pos, points): return sum(1 for nbr in NBRS if add(pos, nbr) in points) def surface_of(bleh): return sum(6 - nbr_cnt(pos, bleh) for pos in bleh) total_surface = surface_of(droplet) print("Part 1:", total_surface) dims = [(min(itr), max(itr)) for itr in [[p[i] for p in droplet] for i in range(3)]] bounds = {(x, y, z) for x in range(dims[0][0] - 1, dims[0][1] + 2) for y in range(dims[1][0] - 1, dims[1][1] + 2) for z in range(dims[2][0] - 1, dims[2][1] + 2)} def search_connected(start, include, exclude): q = PriorityQueue() result = set() result.add(start) q.put(start) while not q.empty(): pos = q.get() for n in NBRS: p = add(pos, n) if p not in include: continue if p in exclude: continue if p in result: continue result.add(p) q.put(p) return result exterior = search_connected((0,0,0), bounds, droplet) interior = (bounds - exterior - droplet) interior_surface = surface_of(interior) print("Part 2:", total_surface - interior_surface)