summaryrefslogtreecommitdiffstats
path: root/9.py
blob: d1a63b916ceb56b011b6bb3d8e2040608359ccb1 (plain)
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 functools import reduce
from utils import open_day
from collections import deque

heatmap = [[int(c) for c in l.rstrip()] for l in open_day(9)]
adj = [(1, 0), (0, 1), (-1, 0), (0, -1)]

def is_low(x, y):
    risk = heatmap[y][x]
    for dx, dy in adj:
        nx = x + dx
        ny = y + dy
        if nx >= 0 and nx < len(heatmap[0]) and ny >= 0 and ny < len(heatmap):
            if heatmap[y+dy][x+dx] <= risk:
                return False
    return True

def basin_size(x, y):
    seen = set()
    queue = deque(((x, y),))
    size = 0
    while queue:
        x, y = queue.popleft()
        if (x, y) in seen:
            continue
        if x < 0 or x >= len(heatmap[0]) or y < 0 or y >= len(heatmap):
            continue
        seen.add((x, y))
        if heatmap[y][x] == 9:
            continue
        size += 1
        for dx, dy in adj:
            queue.append((x + dx, y + dy))
    return size

totrisk = 0
lows = []
for y in range(len(heatmap)):
    for x in range(len(heatmap[y])):
        if is_low(x, y):
            totrisk += 1 + heatmap[y][x]
            lows.append(basin_size(x, y))
print(totrisk)
lows.sort()
print(reduce(lambda x, y: x * y, lows[-3:], 1))