advent-of-code/2024-python/output/day_12.py

74 lines
2.2 KiB
Python
Raw Normal View History

from collections import deque
from output import D, Di, cw, matrix
def solve(data):
grid, H, W = matrix(data)
fence_cost = 0
fence_cost_w_discount = 0
seen = set()
for r in range(H):
for c in range(W):
if (r, c) in seen:
continue
id = grid[r][c]
regions = set()
perimeters = 0
q = deque([(r, c)])
while q:
rc = q.popleft()
if rc in seen:
continue
seen.add(rc)
regions.add(rc)
y, x = rc
for delta_y, delta_x in D:
yn, xn = y + delta_y, x + delta_x
if (0 <= yn < H and 0 <= xn < W) and grid[yn][xn] == id:
q.append((yn, xn))
else:
perimeters += 1
if len(regions) <= 2:
corners = 4
else:
corners = count_corners(regions)
fence_cost += len(regions) * perimeters
fence_cost_w_discount += len(regions) * corners
return fence_cost, fence_cost_w_discount
def count_corners(region):
corners = 0
for y, x in region:
for delta_y, delta_x in D:
# convex corners: one horisontal and one vertical
# neighbor are not members of region
delta_ycw, delta_xcw = cw(delta_y, delta_x)
if (y + delta_y, x + delta_x) not in region and (
y + delta_ycw,
x + delta_xcw,
) not in region:
corners += 1
for delta_y, delta_x in Di:
# concave corners: the diagonal neighbor are not
# member of region, but the connected horisontal
# and vertical neighbors are
if (
(y + delta_y, x + delta_x) not in region
and (y + delta_y, x) in region
and (y, x + delta_x) in region
):
corners += 1
return corners
if __name__ == "__main__":
with open("./input/12.txt", "r") as f:
inp = f.read().strip()
p1, p2 = solve(inp)
print(p1)
print(p2)