did day10 and day12 part 1
This commit is contained in:
1 parent
078c7dc82c
commit
adb6512003
7 files changed
+465
No files matched your search
@@ -0,0 +1,128 @@
|
||||
with open('test.text', 'r') as file:
|
||||
data: str = file.read()
|
||||
|
||||
gardens: list[list[str]] = [[c for c in line.strip()] for line in data.split('\n')]
|
||||
|
||||
x_bound: int = len(gardens[0]) - 1
|
||||
y_bound: int = len(gardens) - 1
|
||||
|
||||
class Coord:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
def __init__(self, x: int, y: int):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f'({self.x}, {self.y})'
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
return other.x == self.x and other.y == self.y
|
||||
|
||||
def __add__(self, other):
|
||||
return Coord(self.x + other.x, self.y + other.y)
|
||||
|
||||
def __sub__(self, other):
|
||||
return Coord(self.x - other.x, self.y - other.y)
|
||||
|
||||
def in_bounds(c: Coord) -> bool:
|
||||
if c.y > y_bound or c.y < 0:
|
||||
return False
|
||||
|
||||
if c.x > x_bound or c.x < 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def neighbor_count(c: Coord) -> int:
|
||||
neighbors = 0
|
||||
|
||||
up, down, left, right = Coord(c.x, c.y - 1), Coord(c.x, c.y + 1), Coord(c.x - 1, c.y), Coord(c.x + 1, c.y)
|
||||
|
||||
v: str = gardens[c.y][c.x]
|
||||
for direction in [up, down, left, right]:
|
||||
if in_bounds(direction):
|
||||
if gardens[direction.y][direction.x] == v:
|
||||
neighbors += 1
|
||||
|
||||
return neighbors
|
||||
|
||||
# Uses a flood fill to find each region, and returns a region as a list of coordinates
|
||||
def flood_fill(start: Coord) -> list[Coord]:
|
||||
filled: list[Coord] = []
|
||||
to_fill: list[Coord] = [start]
|
||||
edges: list[tuple[int, Coord]] = [] # Each edge is a tuple of (direction unit vector, x or y depending on if left, right or up, down)
|
||||
|
||||
v: str = gardens[start.y][start.x]
|
||||
while to_fill:
|
||||
c = to_fill.pop()
|
||||
filled.append(c)
|
||||
|
||||
up, down, left, right = Coord(c.x, c.y - 1), Coord(c.x, c.y + 1), Coord(c.x - 1, c.y), Coord(c.x + 1, c.y)
|
||||
|
||||
for direction in [up, down, left, right]:
|
||||
if in_bounds(direction):
|
||||
if gardens[direction.y][direction.x] == v:
|
||||
if direction not in filled and direction not in to_fill:
|
||||
to_fill.append(direction)
|
||||
continue
|
||||
|
||||
unit_direction = c - direction
|
||||
|
||||
# Means it's up/down
|
||||
if unit_direction.x == 0:
|
||||
if (c.y, unit_direction) not in edges:
|
||||
edges.append((c.y, unit_direction))
|
||||
# Left / Right
|
||||
else:
|
||||
if (c.x, unit_direction) not in edges:
|
||||
edges.append((c.x, unit_direction))
|
||||
|
||||
print(v, len(edges))
|
||||
for edge in edges:
|
||||
print(edge[0], edge[1])
|
||||
|
||||
return filled
|
||||
|
||||
def print_region(region: list[Coord]) -> None:
|
||||
for member in region:
|
||||
print(member, end=' ')
|
||||
print()
|
||||
|
||||
for y, line in enumerate(gardens):
|
||||
for x, char in enumerate(line):
|
||||
print(char if Coord(x, y) in region else ' ', end='')
|
||||
print()
|
||||
|
||||
|
||||
# Part 1
|
||||
|
||||
total_cost = 0
|
||||
checked = gardens.copy()
|
||||
for y, line in enumerate(gardens):
|
||||
for x, char in enumerate(line):
|
||||
if checked[y][x] == "-1":
|
||||
continue
|
||||
|
||||
region = flood_fill(Coord(x, y))
|
||||
area = len(region)
|
||||
|
||||
perimeter = 0
|
||||
for member in region:
|
||||
perimeter += 4 - neighbor_count(member)
|
||||
|
||||
|
||||
for member in region:
|
||||
checked[member.y][member.x] = '-1'
|
||||
|
||||
total_cost += area * perimeter
|
||||
# print(f'A region of {char} plants with price {area} * {perimeter} = {area * perimeter}')
|
||||
|
||||
print(f'Total Cost: {total_cost}')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user