advent-of-code/2024/12/two.py

137 lines
3.6 KiB
Python
Raw Permalink Normal View History

2024-12-25 12:58:02 +01:00
#!/usr/bin/env python3
import sys
input_file = sys.argv[1]
with open(input_file) as fd:
lines = [line.rstrip() for line in fd.readlines()]
height = len(lines)
width = len(lines[0])
visited: set[tuple[int, int]] = set()
directions = [
(0, 1),
(0, -1),
(1, 0),
(-1, 0),
]
def get_region(
pos: tuple[int, int], region: set[tuple[int, int]]
) -> set[tuple[int, int]]:
region.add(pos)
i, j = pos
ochar = lines[i][j]
for direction in directions:
i, j = pos[0] + direction[0], pos[1] + direction[1]
if i not in range(height) or j not in range(width):
continue
if (i, j) in region:
continue
char = lines[i][j]
if char != ochar:
continue
region |= get_region((i, j), region)
return region
# def get_sides(region: set[tuple[int, int]]) -> int:
# peri = 0
# for axis in (0, 1):
# oaxis = 0 if axis else 1
# iss = set([pos[axis] for pos in region])
# sta: set[int] = set()
# sto: set[int] = set()
# for i in iss:
# line = [pos[oaxis] for pos in region if pos[axis] == i]
# line.sort()
# last_j = None
# for j in line:
# if last_j is None:
# sta.add(j)
# elif last_j == j - 1:
# pass
# else:
# sta.add(j)
# sto.add(last_j)
# last_j = j
# if last_j is not None:
# sto.add(last_j)
# peri += len(sta) + len(sto)
# return peri
def get_perimeter(region: set[tuple[int, int]]) -> int:
peri = 0
for axis in (0, 1):
oaxis = 0 if axis else 1
iss = set([pos[axis] for pos in region])
for dire in (-1, 1):
print(47, axis, dire, iss, peri)
for i in iss:
oi = i + dire
line = [pos[oaxis] for pos in region if pos[axis] == i]
line.sort()
# last_j = None
for j in line:
if not axis:
opos = oi, j
else:
opos = j, oi
if opos in region:
continue
peri += 1
return peri
def get_sides(region: set[tuple[int, int]]) -> int:
peri = 0
for axis in (0, 1):
oaxis = 0 if axis else 1
iss = set([pos[axis] for pos in region])
for dire in (-1, 1):
print(47, axis, dire, iss, peri)
for i in iss:
oi = i + dire
line = [pos[oaxis] for pos in region if pos[axis] == i]
line.sort()
last_j = None
for j in line:
if not axis:
opos = oi, j
else:
opos = j, oi
if opos in region:
last_j = None
continue
if last_j == j - 1:
pass
else:
peri += 1
last_j = j
return peri
tprice = 0
for i in range(height):
for j in range(width):
pos = i, j
if pos in visited:
continue
region = get_region(pos, set())
visited |= region
area = len(region)
sides = get_sides(region)
price = area * sides
tprice += price
char = lines[i][j]
print(f"{char}: {area} × {sides} = {price}$")
print(tprice)