Skip to content

Commit 1a02d35

Browse files
author
farbfetzen
committed
Solve 2021 day 9
1 parent 9d4eb39 commit 1a02d35

4 files changed

Lines changed: 95 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
| Year | Stars |
55
|------|------:|
6-
| 2021 | 16|
6+
| 2021 | 18|
77
| 2020 | 50 ⭐ |
88
| 2019 | 44 ⭐ |
99
| 2018 | 8 ⭐ |

input/2021-09-sample.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2199943210
2+
3987894921
3+
9856789892
4+
8767896789
5+
9899965678

python/2021/day09.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# https://adventofcode.com/2021/day/9
2+
3+
4+
from collections import namedtuple
5+
from math import prod
6+
7+
8+
SAMPLE_PATH = "../../input/2021-09-sample.txt"
9+
INPUT_PATH = "../../input/2021-09-input.txt"
10+
Point = namedtuple("Point", ("x", "y"))
11+
12+
13+
def get_data(filename):
14+
with open(filename) as file:
15+
data = file.read().splitlines()
16+
heightmap = tuple(tuple(int(x) for x in list(line)) for line in data)
17+
low_points = get_low_points(heightmap)
18+
return heightmap, low_points
19+
20+
21+
def get_neighbors(x, y, max_x, max_y):
22+
neighbors = []
23+
if x > 0:
24+
neighbors.append(Point(x - 1, y))
25+
if x < max_x:
26+
neighbors.append(Point(x + 1, y))
27+
if y > 0:
28+
neighbors.append(Point(x, y - 1))
29+
if y < max_y:
30+
neighbors.append(Point(x, y + 1))
31+
return neighbors
32+
33+
34+
def get_low_points(heightmap):
35+
low_points = []
36+
max_x = len(heightmap[0]) - 1
37+
max_y = len(heightmap) - 1
38+
for y, row in enumerate(heightmap):
39+
for x, height in enumerate(row):
40+
neighbors = get_neighbors(x, y, max_x, max_y)
41+
if all(height < heightmap[n.y][n.x] for n in neighbors):
42+
low_points.append(Point(x, y))
43+
return low_points
44+
45+
46+
def flood_fill(heightmap, origin, max_x, max_y):
47+
neighbors = [origin]
48+
basin_members = {origin}
49+
while neighbors:
50+
current = neighbors.pop()
51+
new_neighbors = get_neighbors(current.x, current.y, max_x, max_y)
52+
for nn in new_neighbors:
53+
# Assuming all basins are surrounded by nines, which is true for the sample.
54+
if nn not in basin_members and heightmap[nn.y][nn.x] < 9:
55+
neighbors.append(nn)
56+
basin_members.add(nn)
57+
return len(basin_members)
58+
59+
60+
def part_1(heightmap, low_points):
61+
return sum(heightmap[lp.y][lp.x] + 1 for lp in low_points)
62+
63+
64+
def part_2(heightmap, low_points):
65+
max_x = len(heightmap[0]) - 1
66+
max_y = len(heightmap) - 1
67+
basin_sizes = [flood_fill(heightmap, lp, max_x, max_y) for lp in low_points]
68+
basin_sizes.sort(reverse=True)
69+
return prod(basin_sizes[:3])
70+
71+
72+
if __name__ == "__main__":
73+
sample_data = get_data(SAMPLE_PATH)
74+
assert part_1(*sample_data) == 15
75+
assert part_2(*sample_data) == 1134
76+
77+
challenge_data = get_data(INPUT_PATH)
78+
print(part_1(*challenge_data)) # 554
79+
print(part_2(*challenge_data)) # 1017792

python/2021/test2021.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import day06
99
import day07
1010
import day08
11+
import day09
1112

1213

1314
class Test2021(unittest.TestCase):
@@ -90,6 +91,15 @@ def test_08(self):
9091
self.assertEqual(day08.part_1(challenge_data), 352)
9192
self.assertEqual(day08.part_2(challenge_data), 936117)
9293

94+
def test_09(self):
95+
sample_data = day09.get_data(day09.SAMPLE_PATH)
96+
self.assertEqual(day09.part_1(*sample_data), 15)
97+
self.assertEqual(day09.part_2(*sample_data), 1134)
98+
99+
challenge_data = day09.get_data(day09.INPUT_PATH)
100+
self.assertEqual(day09.part_1(*challenge_data), 554)
101+
self.assertEqual(day09.part_2(*challenge_data), 1017792)
102+
93103

94104
if __name__ == "__main__":
95105
unittest.main()

0 commit comments

Comments
 (0)