-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday12.py
45 lines (35 loc) · 1.47 KB
/
day12.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from collections import defaultdict
grid = {complex(x, y): c for y, line in enumerate(open('input12.txt'))
for x, c in enumerate(line.strip())}
directions = [1, 1j, -1, -1j]
regions = defaultdict(list)
def is_in_region(pos, c):
for region in regions[c]:
if pos in region: return True
return False
def construct_region(region, pos, c):
region.add(pos)
for d in directions:
if (new_pos := pos + d) not in region and grid.get(new_pos) == c:
region.update(construct_region(region, new_pos, c))
return region
def area(region):
return len(region)
def perimeter(region):
return sum([1 for pos in region for d in directions if pos + d not in region])
def sides(region):
sides = {(d, pos + d) for pos in region for d in directions if pos + d not in region}
total_sides = 0
while sides and (total_sides := total_sides + 1):
d, pos = sides.pop()
new_pos = pos
while (d, new_pos := new_pos + (d*1j)) in sides: sides.remove((d, new_pos))
new_pos = pos
while (d, new_pos := new_pos + (d*-1j)) in sides: sides.remove((d, new_pos))
return total_sides
list(regions[c].append(construct_region(set(), pos, c)) for pos, c in grid.items()
if not is_in_region(pos, c))
# Part 1
print(sum(area(r)*perimeter(r) for rs in regions.values() for r in rs))
# Part 2
print(sum(area(r)*sides(r) for rs in regions.values() for r in rs))