diff --git a/12/12.py b/12/12.py new file mode 100644 index 0000000..b67ddb2 --- /dev/null +++ b/12/12.py @@ -0,0 +1,89 @@ +from collections import defaultdict +d4 = [(-1, 0), (0, 1), (1, 0), (0, -1)] + + + +def make_field(data): + data = data.strip().split("\n") + data = ['.'*len(data[0])] + data + ['.'*len(data[0])] + data = ['.'+x+'.' for x in data] + return data + +def regions(data, collect=len): + def walk(i, j, c): + nonlocal borders + if data[i][j]!=c: + return + if (i, j) not in region: + region.add((i, j)) + for di, dj in d4: + if (i+di, j+dj) not in region: + borders += 1 + else: + borders -= 1 + for di, dj in d4: + walk(i+di, j+dj, c) + unmarked = {(i, j) for i in range(1, len(data)-1) for j in range(1, len(data)-1)} + regions = [] + while unmarked: + i, j = next(iter(unmarked)) + region = set() + borders = 0 + walk(i, j, data[i][j]) + regions.append((collect(region), borders)) + unmarked -= region + return regions + +def sides(data): + for region, _ in regions(data, collect=lambda x: x): + net = defaultdict(lambda: [0,0,0,0]) + for i, j in region: + net[(i, j)][3] = 1 + net[(i+1, j)][0] = 1 + net[(i, j+1)][2] = 1 + net[(i+1, j+1)][1] = 1 + net2 = defaultdict(list) + for (i, j), (a,b,c,d) in net.items(): + if a!=d: + net2[(i, j)].append((i, j+1)) + if a!=b: + net2[(i, j)].append((i-1, j)) + if b!=c: + net2[(i, j)].append((i, j-1)) + if c!=d: + net2[(i, j)].append((i+1, j)) + borders = 0 + while net2: + s = min(net2) + p = s + n = net2[s][0] + net2[s].remove(n) + + borders += 1 + while not n==s: + pi, pj = p + ni, nj = n + net2[n].remove(p) + if len(net2[n])!=1: + a = (ni + nj-pj, nj + ni-pi) + else: + a = (ai, aj) = net2[n][0] + net2[n].remove(a) + if len(net2[n])==0: + del net2[n] + if not((abs(ni-pi)==abs(ai-ni)==1) or (abs(nj-pj)==abs(aj-nj)==1)): + borders += 1 + p = n + n = a + del net2[n] + yield len(region), borders + + +data = open("input.txt").read() + +print(sum(a*b for a, b in regions(make_field(data)))) + +print(sum(a*b for a, b in sides(make_field(data)))) + +import cProfile +cProfile.run('sum(a*b for a, b in sides(make_field(data)))')