Solve 2024:12 p2 "Garden Groups"
Funny that original 2023 day 5 also was a PITA to figure out. Pt 1 was solved using BFS to flood-fill. After trying some different methods for pt 2, including: - wallcrawling, - side couting, - corner counting I never produced code to get past the test cases. - Wall crawling are hard due to overlapping regions. - corner couting and side counting are both hard, but will act as equally good solutions (since side count equals corner count). - Concave corners are hard, convex corners are easy. The final code is based on the posts on the solutions megathread. Changes: - Keep all areas in a set, defining a region. - find all convex and concave corners in each region. A new helper got introduced: Di, storing all diagonal neighbors for grid traversing. Convex corners: .. R. .R .. R. .. .. .R Concave corners: RR .R R. RR .R RR RR R.
This commit is contained in:
parent
1e807b5daf
commit
9a7a9c878b
2 changed files with 53 additions and 61 deletions
|
|
@ -9,6 +9,13 @@ D = [
|
|||
(0, -1),
|
||||
]
|
||||
|
||||
Di = [
|
||||
(-1, -1),
|
||||
(-1, 1),
|
||||
(1, -1),
|
||||
(1, 1),
|
||||
]
|
||||
|
||||
# Directions for 2D matrices, as a dict with keys U, R, D, L
|
||||
DD = {
|
||||
"U": (-1, 0),
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import re
|
||||
from collections import Counter, defaultdict, deque
|
||||
from heapq import heappop, heappush
|
||||
from itertools import chain, combinations, compress, permutations
|
||||
from collections import deque
|
||||
|
||||
from output import ADJ, DD, D, ccw, cw, ints, matrix, mdbg, mhd, vdbg
|
||||
from output import D, Di, cw, matrix
|
||||
|
||||
|
||||
def solve(data):
|
||||
grid, H, W = matrix(data)
|
||||
p1 = 0
|
||||
fence_cost = 0
|
||||
fence_cost_w_discount = 0
|
||||
seen = set()
|
||||
for r, row in enumerate(grid):
|
||||
for c, col in enumerate(row):
|
||||
for r in range(H):
|
||||
for c in range(W):
|
||||
if (r, c) in seen:
|
||||
continue
|
||||
areas = 0
|
||||
id = grid[r][c]
|
||||
regions = set()
|
||||
perimeters = 0
|
||||
q = deque([(r, c)])
|
||||
while q:
|
||||
|
|
@ -22,67 +21,53 @@ def solve(data):
|
|||
if rc in seen:
|
||||
continue
|
||||
seen.add(rc)
|
||||
areas += 1
|
||||
regions.add(rc)
|
||||
y, x = rc
|
||||
for dy, dx in D:
|
||||
if (0 <= y + dy < H and 0 <= x + dx < W) and grid[y + dy][
|
||||
x + dx
|
||||
] == col:
|
||||
q.append((y + dy, x + dx))
|
||||
for delta_y, delta_x in D:
|
||||
yn, xn = y + delta_y, x + delta_x
|
||||
if (0 <= yn < H and 0 <= xn < W) and grid[yn][xn] == id:
|
||||
q.append((yn, xn))
|
||||
else:
|
||||
perimeters += 1
|
||||
p1 += areas * perimeters
|
||||
p2 = None
|
||||
return p1, p2
|
||||
if len(regions) <= 2:
|
||||
corners = 4
|
||||
else:
|
||||
corners = count_corners(regions)
|
||||
fence_cost += len(regions) * perimeters
|
||||
fence_cost_w_discount += len(regions) * corners
|
||||
return fence_cost, fence_cost_w_discount
|
||||
|
||||
|
||||
def count_corners(region):
|
||||
corners = 0
|
||||
for y, x in region:
|
||||
for delta_y, delta_x in D:
|
||||
# convex corners: one horisontal and one vertical
|
||||
# neighbor are not members of region
|
||||
delta_ycw, delta_xcw = cw(delta_y, delta_x)
|
||||
if (y + delta_y, x + delta_x) not in region and (
|
||||
y + delta_ycw,
|
||||
x + delta_xcw,
|
||||
) not in region:
|
||||
corners += 1
|
||||
for delta_y, delta_x in Di:
|
||||
# concave corners: the diagonal neighbor are not
|
||||
# member of region, but the connected horisontal
|
||||
# and vertical neighbors are
|
||||
if (
|
||||
(y + delta_y, x + delta_x) not in region
|
||||
and (y + delta_y, x) in region
|
||||
and (y, x + delta_x) in region
|
||||
):
|
||||
corners += 1
|
||||
return corners
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import os
|
||||
|
||||
# use dummy data
|
||||
inp = """
|
||||
RRRRIICCFF
|
||||
RRRRIICCCF
|
||||
VVRRRCCFFF
|
||||
VVRCCCJFFF
|
||||
VVVVCJJCFE
|
||||
VVIVCCJJEE
|
||||
VVIIICJJEE
|
||||
MIIIIIJJEE
|
||||
MIIISIJEEE
|
||||
MMMISSJEEE
|
||||
""".strip()
|
||||
|
||||
"""
|
||||
A region of R plants with price 12 * 18 = 216.
|
||||
A region of I plants with price 4 * 8 = 32.
|
||||
A region of C plants with price 14 * 28 = 392.
|
||||
A region of F plants with price 10 * 18 = 180.
|
||||
A region of V plants with price 13 * 20 = 260.
|
||||
A region of J plants with price 11 * 20 = 220.
|
||||
A region of C plants with price 1 * 4 = 4.
|
||||
A region of E plants with price 13 * 18 = 234.
|
||||
A region of I plants with price 14 * 22 = 308.
|
||||
A region of M plants with price 5 * 12 = 60.
|
||||
A region of S plants with price 3 * 8 = 24.
|
||||
"""
|
||||
|
||||
# uncomment to instead use stdin
|
||||
# import sys; inp = sys.stdin.read().strip()
|
||||
|
||||
# uncomment to use AoC provided puzzle input
|
||||
with open("./input/12.txt", "r") as f:
|
||||
inp = f.read().strip()
|
||||
|
||||
# uncomment to do initial data processing shared by part 1-2
|
||||
p1, p2 = solve(inp)
|
||||
|
||||
print(p1)
|
||||
os.system(f"echo {p1} | wl-copy")
|
||||
# print(p2)
|
||||
# os.system(f"echo {p2} | wl-copy")
|
||||
|
||||
# uncomment and replace 0 with actual output to refactor code
|
||||
# and ensure nonbreaking changes
|
||||
assert p1 == 1446042
|
||||
# assert p2 == 0
|
||||
print(p2)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue