aoc2024/d12/run.py

57 lines
1.7 KiB
Python
Raw Normal View History

import sys
from grid import *
G = [list(l) for l in sys.stdin.read().strip().split("\n")]
def build_zone(G, x:int, y:int, zone:set[tuple[int,int]]):
zone.add((x, y))
v = get_in_grid(G, x, y)
for dx, dy in MOVE4:
xn = x +dx
yn = y + dy
if (xn, yn) not in zone:
if get_in_grid(G, xn, yn) == v:
build_zone(G, xn, yn, zone)
def perimeter(zone:set[tuple[int,int]]) -> int:
return sum (
(x+dx, y+dy) not in zone
for (x,y) in zone
for (dx, dy) in MOVE4)
def corners(zone:set[tuple[int,int]]) -> int:
corners = 0
for x,y in zone:
# define tile neighbourhood
[N,E,S,W] = [(x+dx,y+dy)in zone for (dx,dy) in MOVE4]
[SE,NW,NE,SW] = [(x+dx,y+dy)in zone for (dx,dy) in DIAG4]
# alone == no adjacent
if not (W or N or E or S): corners+=4
# touches zone on just 1 side
if (W+N+E+S==1): corners+=2
# outside corners
if (S and E and not N and not W): corners+=1
if (S and W and not N and not E): corners+=1
if (N and E and not S and not W): corners+=1
if (N and W and not S and not E): corners+=1
# inside corners
if (E and N and not NE): corners+=1
if (E and S and not SE): corners+=1
if (W and N and not NW): corners+=1
if (W and S and not SW): corners+=1
return corners
T1 = T2 = 0
checked = set()
W, H = grid_geom(G)
for y in range(W):
for x in range(H):
if (x,y) in checked: continue
zone = set()
build_zone(G, x, y, zone)
area = len(zone)
T1 += area * perimeter(zone)
T2 += area * corners(zone)
checked |= zone
print(T1, T2)