summaryrefslogtreecommitdiff
path: root/2024/aoc2024-d12.py
diff options
context:
space:
mode:
Diffstat (limited to '2024/aoc2024-d12.py')
-rw-r--r--2024/aoc2024-d12.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/2024/aoc2024-d12.py b/2024/aoc2024-d12.py
new file mode 100644
index 0000000..b7ac378
--- /dev/null
+++ b/2024/aoc2024-d12.py
@@ -0,0 +1,83 @@
+#advent of code 2024
+#day 12
+#we needed area of the plot and its perimiter
+#we floodfill given plot and store the coordinates of the plants
+#then, on the borders, we register the coordinates of the plants
+#that are adjacent to our plot and the direction from which it was
+#registered during floodfill. the length of this set (perim) is the perimiter
+#then, for part 2, we group the points in perim set by their direction
+#(3rd parameter), then we sort each group based on the coordinate
+#that is changing, that is: if the fence was registered from the north,
+#then it is part of the north-facing fence, so we sort it by the x-axis
+#identical for southern and similar for east/west (y-axis)
+#iterate over every fence point, if the gap is greater 1 then increment
+#the amount of sides. I probably should make a drawing because
+#I'll forget what it does in the future despite writing this comment
+grid = {};
+f = open("12.in","r");
+for y,l in enumerate(f):
+ for x,c in enumerate(l.strip()):
+ grid[(x,y)]=c;
+f.close();
+
+dirs = [(1,0),(0,1),(-1,0),(0,-1)];
+visited = set();
+
+def getAdjacent(pos,l):
+ adj = [];
+ vis = set();
+ xp, yp = pos;
+ for di,d in enumerate(dirs):
+ dx,dy = d;
+ if grid.get((xp+dx,yp+dy),".") == l:
+ adj.append((xp+dx,yp+dy));
+ else:
+ vis.add((xp+dx,yp+dy,di));
+ return adj, vis;
+
+def sides(perimiter):
+ SidesTotal = 0;
+ NumberOfSides = {};
+ PerimsGrouped = {};
+ for di in range(4):
+ NumberOfSides[di] = 0;
+ PerimsGrouped[di] = [m for m in perimiter if m[2]==di];
+ PerimsGrouped[di] = sorted(PerimsGrouped[di], key=lambda m: (m[di%2],m[(di+1)%2]));
+ if len(PerimsGrouped[di]) == 0:
+ continue;
+ else:
+ NumberOfSides[di] += 1;
+ prevx,prevy,prevd = PerimsGrouped[di][0];
+ for PerPos in PerimsGrouped[di][1:]:
+ x,y,d = PerPos;
+ if not(abs(x-prevx)==di%2 and abs(y-prevy) ==(di+1)%2):
+ NumberOfSides[di] += 1;
+ prevx,prevy,prevd = x,y,d;
+ SidesTotal += NumberOfSides[di];
+ return SidesTotal;
+
+def fill(startpos, letter):
+ queue = [startpos];
+ perim = set(); #add points that aren't part of the area but are adjacent
+ v = set(); #visited points, that is: the area
+ while queue:
+ px,py = queue.pop();
+ if (px,py) in v: continue;
+ visited.add((px,py));
+ v.add((px,py));
+ NextValid, NextBorders = getAdjacent((px,py),letter);
+ queue.extend(NextValid);
+ perim = perim.union(NextBorders);
+ return len(v), len(perim), sides(perim);
+
+part1 = 0;
+part2 = 0;
+for g in grid:
+ if g in visited:continue;
+ L = grid[g];
+ LandArea, LandPerim, LandSides = fill(g,L);
+ part1 += LandArea*LandPerim;
+ part2 += LandArea*LandSides;
+
+print("part 1 =", part1);
+print("part 2 =", part2);