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)