-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday12.py
More file actions
executable file
·110 lines (90 loc) · 3.07 KB
/
day12.py
File metadata and controls
executable file
·110 lines (90 loc) · 3.07 KB
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from collections import deque
from aoc_utils import * # type: ignore
from aocd import get_data
data = get_data(year=2024, day=12, block=True)
def parse(data):
grid = Grid.parse(data)
regions = []
history = set()
for yx, c in grid.row_major_with_index():
if yx in history:
continue
queue = deque([yx])
region = set([yx])
while queue:
np = queue.popleft()
for ayx, cc in grid.around_with_index(np, corners=False):
if cc != c or ayx in history:
continue
history.add(ayx)
region.add(ayx)
queue.append(ayx)
regions.append(region)
return regions
def around(point):
y, x = point
yield (y + 1, x)
yield (y - 1, x)
yield (y, x + 1)
yield (y, x - 1)
def part_one(data):
regions = parse(data)
price = 0
for region in regions:
area = len(region)
perimeter = 0
for point in region:
for a in around(point):
perimeter += a not in region
price += area * perimeter
return price
def around_with_direction(point):
y, x = point
for d in Direction.cardinal():
dy, dx = d.value
yield (y + dy, x + dx), d
def part_two(data):
regions = parse(data)
price = 0
for region in regions:
area = len(region)
sides = []
for point in sorted(region):
for around, around_direction in around_with_direction(point):
if around not in region:
ay, ax = around
match = False
for side_direction, points in sides:
if side_direction != around_direction:
continue
for sy, sx in points:
if (
(
side_direction is Direction.WEST
or side_direction is Direction.EAST
)
and ax == sx
and abs(ay - sy) == 1
):
points.add(around)
match = True
break
elif (
(
side_direction is Direction.NORTH
or side_direction is Direction.SOUTH
)
and ay == sy
and abs(ax - sx) == 1
):
points.add(around)
match = True
break
if match:
break
else:
sides.append((around_direction, set([around])))
price += area * len(sides)
return price
print(part_one(data))
print(part_two(data))