generated from public/aoc_template
Day 10 - cleanup
This commit is contained in:
parent
c83cb8598b
commit
606a4bf4b2
206
day10.py
206
day10.py
@ -4,63 +4,82 @@ from tools.coordinate import Coordinate
|
|||||||
from tools.grid import Grid
|
from tools.grid import Grid
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
VALID_NEIGHBOURS = {
|
|
||||||
Coordinate(1, 0): {
|
LOOKUP = {
|
||||||
"check": ["F", "-", "L", "S"],
|
"|": {
|
||||||
"valid": ["7", "-", "J"],
|
Coordinate(0, 1): {"o_dir": [Coordinate(-1, 0)], "i_dir": [Coordinate(1, 0)], "n_dir": Coordinate(0, 1)},
|
||||||
|
Coordinate(0, -1): {"o_dir": [Coordinate(1, 0)], "i_dir": [Coordinate(-1, 0)], "n_dir": Coordinate(0, -1)},
|
||||||
},
|
},
|
||||||
Coordinate(0, 1): {
|
"-": {
|
||||||
"check": ["7", "|", "F", "S"],
|
Coordinate(1, 0): {"o_dir": [Coordinate(0, 1)], "i_dir": [Coordinate(0, -1)], "n_dir": Coordinate(1, 0)},
|
||||||
"valid": ["J", "|", "L"],
|
Coordinate(-1, 0): {"o_dir": [Coordinate(0, -1)], "i_dir": [Coordinate(0, 1)], "n_dir": Coordinate(-1, 0)},
|
||||||
},
|
},
|
||||||
Coordinate(-1, 0): {
|
"7": {
|
||||||
"check": ["J", "-", "7", "S"],
|
Coordinate(1, 0): {
|
||||||
"valid": ["F", "-", "L"],
|
"o_dir": None,
|
||||||
|
"i_dir": [Coordinate(0, -1), Coordinate(1, 0)],
|
||||||
|
"n_dir": Coordinate(0, 1),
|
||||||
|
},
|
||||||
|
Coordinate(0, -1): {
|
||||||
|
"o_dir": [Coordinate(1, 0), Coordinate(0, -1)],
|
||||||
|
"i_dir": None,
|
||||||
|
"n_dir": Coordinate(-1, 0),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Coordinate(0, -1): {
|
"J": {
|
||||||
"check": ["L", "|", "J", "S"],
|
Coordinate(0, 1): {
|
||||||
"valid": ["F", "|", "7"],
|
"o_dir": None,
|
||||||
|
"i_dir": [Coordinate(1, 0), Coordinate(0, 1)],
|
||||||
|
"n_dir": Coordinate(-1, 0),
|
||||||
|
},
|
||||||
|
Coordinate(1, 0): {
|
||||||
|
"o_dir": [Coordinate(1, 0), Coordinate(0, 1)],
|
||||||
|
"i_dir": None,
|
||||||
|
"n_dir": Coordinate(0, -1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"F": {
|
||||||
|
Coordinate(0, -1): {
|
||||||
|
"o_dir": None,
|
||||||
|
"i_dir": [Coordinate(-1, 0), Coordinate(0, -1)],
|
||||||
|
"n_dir": Coordinate(1, 0),
|
||||||
|
},
|
||||||
|
Coordinate(-1, 0): {
|
||||||
|
"o_dir": [Coordinate(-1, 0), Coordinate(0, -1)],
|
||||||
|
"i_dir": None,
|
||||||
|
"n_dir": Coordinate(0, 1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"L": {
|
||||||
|
Coordinate(-1, 0): {
|
||||||
|
"o_dir": None,
|
||||||
|
"i_dir": [Coordinate(-1, 0), Coordinate(0, 1)],
|
||||||
|
"n_dir": Coordinate(0, -1),
|
||||||
|
},
|
||||||
|
Coordinate(0, 1): {
|
||||||
|
"o_dir": [Coordinate(-1, 0), Coordinate(0, 1)],
|
||||||
|
"i_dir": None,
|
||||||
|
"n_dir": Coordinate(1, 0),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def remove_clutter(grid: Grid, start: Coordinate):
|
def remove_clutter(grid: Grid, start: Coordinate):
|
||||||
pipe_coords = set()
|
pipe_coords = set()
|
||||||
pipe_coords.add(start)
|
for x in LOOKUP[grid.get(start)]:
|
||||||
q = deque()
|
dir_ = LOOKUP[grid.get(start)][x]["n_dir"]
|
||||||
q.append(start)
|
break
|
||||||
while q:
|
while start not in pipe_coords:
|
||||||
cur = q.pop()
|
pipe_coords.add(start)
|
||||||
for c, v in VALID_NEIGHBOURS.items():
|
start += dir_
|
||||||
dc = cur + c
|
dir_ = LOOKUP[grid.get(start)][dir_]["n_dir"]
|
||||||
if dc not in pipe_coords and grid.get(cur) in v["check"] and grid.get(dc) in v["valid"]:
|
|
||||||
pipe_coords.add(dc)
|
|
||||||
q.append(dc)
|
|
||||||
|
|
||||||
for c in grid.getActiveCells():
|
for c in grid.getActiveCells():
|
||||||
if c not in pipe_coords:
|
if c not in pipe_coords:
|
||||||
grid.set(c, False)
|
grid.set(c, False)
|
||||||
|
|
||||||
|
|
||||||
def get_farthest(grid: Grid, start: Coordinate) -> int:
|
|
||||||
q = deque()
|
|
||||||
q.append((0, start))
|
|
||||||
visited = set()
|
|
||||||
max_dist = 0
|
|
||||||
while q:
|
|
||||||
dist, cur = q.popleft()
|
|
||||||
if cur in visited:
|
|
||||||
continue
|
|
||||||
visited.add(cur)
|
|
||||||
for c, v in VALID_NEIGHBOURS.items():
|
|
||||||
dc = cur + c
|
|
||||||
if dc not in visited and grid.get(cur) in v["check"] and grid.get(dc) in v["valid"]:
|
|
||||||
q.append((dist + 1, dc))
|
|
||||||
max_dist = max(max_dist, dist + 1)
|
|
||||||
|
|
||||||
return max_dist
|
|
||||||
|
|
||||||
|
|
||||||
def get_area(grid: Grid, start: Coordinate) -> set[Coordinate]:
|
def get_area(grid: Grid, start: Coordinate) -> set[Coordinate]:
|
||||||
if grid.get(start):
|
if grid.get(start):
|
||||||
return set()
|
return set()
|
||||||
@ -81,66 +100,7 @@ def get_area(grid: Grid, start: Coordinate) -> set[Coordinate]:
|
|||||||
return area
|
return area
|
||||||
|
|
||||||
|
|
||||||
def walk(grid: Grid) -> int:
|
def walk(grid: Grid, part2: bool = False) -> int:
|
||||||
LOOKUP = {
|
|
||||||
"|": {
|
|
||||||
Coordinate(0, 1): {"o_dir": [Coordinate(-1, 0)], "i_dir": [Coordinate(1, 0)], "n_dir": Coordinate(0, 1)},
|
|
||||||
Coordinate(0, -1): {"o_dir": [Coordinate(1, 0)], "i_dir": [Coordinate(-1, 0)], "n_dir": Coordinate(0, -1)},
|
|
||||||
},
|
|
||||||
"-": {
|
|
||||||
Coordinate(1, 0): {"o_dir": [Coordinate(0, 1)], "i_dir": [Coordinate(0, -1)], "n_dir": Coordinate(1, 0)},
|
|
||||||
Coordinate(-1, 0): {"o_dir": [Coordinate(0, -1)], "i_dir": [Coordinate(0, 1)], "n_dir": Coordinate(-1, 0)},
|
|
||||||
},
|
|
||||||
"7": {
|
|
||||||
Coordinate(1, 0): {
|
|
||||||
"o_dir": None,
|
|
||||||
"i_dir": [Coordinate(0, -1), Coordinate(1, 0)],
|
|
||||||
"n_dir": Coordinate(0, 1),
|
|
||||||
},
|
|
||||||
Coordinate(0, -1): {
|
|
||||||
"o_dir": [Coordinate(1, 0), Coordinate(0, -1)],
|
|
||||||
"i_dir": None,
|
|
||||||
"n_dir": Coordinate(-1, 0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"J": {
|
|
||||||
Coordinate(0, 1): {
|
|
||||||
"o_dir": None,
|
|
||||||
"i_dir": [Coordinate(1, 0), Coordinate(0, 1)],
|
|
||||||
"n_dir": Coordinate(-1, 0),
|
|
||||||
},
|
|
||||||
Coordinate(1, 0): {
|
|
||||||
"o_dir": [Coordinate(1, 0), Coordinate(0, 1)],
|
|
||||||
"i_dir": None,
|
|
||||||
"n_dir": Coordinate(0, -1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"F": {
|
|
||||||
Coordinate(0, -1): {
|
|
||||||
"o_dir": None,
|
|
||||||
"i_dir": [Coordinate(-1, 0), Coordinate(0, -1)],
|
|
||||||
"n_dir": Coordinate(1, 0),
|
|
||||||
},
|
|
||||||
Coordinate(-1, 0): {
|
|
||||||
"o_dir": [Coordinate(-1, 0), Coordinate(0, -1)],
|
|
||||||
"i_dir": None,
|
|
||||||
"n_dir": Coordinate(0, 1),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"L": {
|
|
||||||
Coordinate(-1, 0): {
|
|
||||||
"o_dir": None,
|
|
||||||
"i_dir": [Coordinate(-1, 0), Coordinate(0, 1)],
|
|
||||||
"n_dir": Coordinate(0, -1),
|
|
||||||
},
|
|
||||||
Coordinate(0, 1): {
|
|
||||||
"o_dir": [Coordinate(-1, 0), Coordinate(0, 1)],
|
|
||||||
"i_dir": None,
|
|
||||||
"n_dir": Coordinate(1, 0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = None
|
cur = None
|
||||||
for x in grid.rangeX():
|
for x in grid.rangeX():
|
||||||
for y in grid.rangeY():
|
for y in grid.rangeY():
|
||||||
@ -152,32 +112,38 @@ def walk(grid: Grid) -> int:
|
|||||||
|
|
||||||
assert grid.get(cur) == "F"
|
assert grid.get(cur) == "F"
|
||||||
|
|
||||||
|
pipe_len = 0
|
||||||
direction = Coordinate(0, 1)
|
direction = Coordinate(0, 1)
|
||||||
outside = get_area(grid, cur + Coordinate(0, -1))
|
outside = get_area(grid, cur + Coordinate(0, -1))
|
||||||
inside = set()
|
inside = set()
|
||||||
visited = set()
|
visited = set()
|
||||||
while cur not in visited:
|
while cur not in visited:
|
||||||
|
pipe_len += 1
|
||||||
visited.add(cur)
|
visited.add(cur)
|
||||||
cur += direction
|
cur += direction
|
||||||
c = grid.get(cur)
|
c = grid.get(cur)
|
||||||
oc = LOOKUP[c][direction]["o_dir"]
|
if part2:
|
||||||
ic = LOOKUP[c][direction]["i_dir"]
|
oc = LOOKUP[c][direction]["o_dir"]
|
||||||
|
ic = LOOKUP[c][direction]["i_dir"]
|
||||||
|
|
||||||
if oc is not None:
|
if oc is not None:
|
||||||
for doc in oc:
|
for doc in oc:
|
||||||
check = cur + doc
|
check = cur + doc
|
||||||
if check not in outside and not grid.get(check):
|
if check not in outside and not grid.get(check):
|
||||||
outside |= get_area(grid, check)
|
outside |= get_area(grid, check)
|
||||||
|
|
||||||
if ic is not None:
|
if ic is not None:
|
||||||
for dic in ic:
|
for dic in ic:
|
||||||
check = cur + dic
|
check = cur + dic
|
||||||
if check not in inside and not grid.get(check):
|
if check not in inside and not grid.get(check):
|
||||||
inside |= get_area(grid, check)
|
inside |= get_area(grid, check)
|
||||||
|
|
||||||
direction = LOOKUP[c][direction]["n_dir"]
|
direction = LOOKUP[c][direction]["n_dir"]
|
||||||
|
|
||||||
return len(inside)
|
if part2:
|
||||||
|
return len(inside)
|
||||||
|
else:
|
||||||
|
return pipe_len // 2
|
||||||
|
|
||||||
|
|
||||||
class Day(AOCDay):
|
class Day(AOCDay):
|
||||||
@ -196,7 +162,7 @@ class Day(AOCDay):
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
def parse_input(self) -> (Grid, Coordinate):
|
def parse_input(self) -> Grid:
|
||||||
grid = Grid()
|
grid = Grid()
|
||||||
start = None
|
start = None
|
||||||
for y, line in enumerate(self.getInput()):
|
for y, line in enumerate(self.getInput()):
|
||||||
@ -227,15 +193,13 @@ class Day(AOCDay):
|
|||||||
grid.set(start, "-")
|
grid.set(start, "-")
|
||||||
|
|
||||||
remove_clutter(grid, start)
|
remove_clutter(grid, start)
|
||||||
return grid, start
|
return grid
|
||||||
|
|
||||||
def part1(self) -> Any:
|
def part1(self) -> Any:
|
||||||
grid, start = self.parse_input()
|
return walk(self.parse_input())
|
||||||
return get_farthest(grid, start)
|
|
||||||
|
|
||||||
def part2(self) -> Any:
|
def part2(self) -> Any:
|
||||||
grid, _ = self.parse_input()
|
return walk(self.parse_input(), True)
|
||||||
return walk(grid)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user