-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.py
124 lines (110 loc) · 3.96 KB
/
script.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import functools
from GhostyUtils import aoc
from GhostyUtils.grid import Grid
from GhostyUtils.vec2 import Vec2, Dir
pipe_connects = {'|': [Dir.NORTH, Dir.SOUTH],
'-': [Dir.EAST, Dir.WEST],
'L': [Dir.NORTH, Dir.EAST],
'J': [Dir.NORTH, Dir.WEST],
'7': [Dir.SOUTH, Dir.WEST],
'F': [Dir.SOUTH, Dir.EAST],
'.': [],
'S': [Dir.NORTH, Dir.SOUTH, Dir.EAST, Dir.WEST]}
dir_connects = {Dir.NORTH: Dir.SOUTH,
Dir.SOUTH: Dir.NORTH,
Dir.EAST: Dir.WEST,
Dir.WEST: Dir.EAST}
def s_type(grid: Grid, s_pos: Vec2):
s_dirs = [d for d in pipe_connects['S']
if dir_connects[d] in pipe_connects[grid[s_pos + d.as_vec2()]]]
return [pipe for pipe, dirs in pipe_connects.items() if dirs == s_dirs][0]
def find_path(grid: Grid, s_pos: Vec2):
pos = s_pos
path = [s_pos]
came_from = None
done = False
while not done:
# filter out the direction we came from, we can't go backwards
search_dirs = [d for d in pipe_connects[grid[pos]] if d != came_from]
for d in search_dirs:
# get the pipe in the direction we're searching
pipe = grid[pos + d.as_vec2()]
# if it's S, we're done
if pipe == 'S':
done = True
break
# if the pipe we're looking at connects to our current position,
# move to that pipe and add it to our path
if dir_connects[d] in pipe_connects[pipe]:
pos = pos + d.as_vec2()
path.append(pos)
came_from = dir_connects[d]
break
return path
if __name__ == '__main__':
rows = aoc.read_lines()
pipe_grid = Grid(rows)
width = pipe_grid.width()
height = pipe_grid.height()
s_pos = pipe_grid.find('S')
path = find_path(pipe_grid, s_pos)
print(len(path) // 2)
expand = {'|': ['.|.',
'.|.',
'.|.'],
'-': ['...',
'---',
'...'],
'L': ['.|.',
'.L-',
'...'],
'J': ['.|.',
'-J.',
'...'],
'7': ['...',
'-7.',
'.|.'],
'F': ['...',
'.F-',
'.|.'],
'.': ['...',
'...',
'...']}
big_width = width*3
big_height = height*3
big_grid = Grid(('.'*big_width for _ in range(big_height)))
s_pipe = s_type(pipe_grid, s_pos)
for y, row in enumerate(pipe_grid.by_rows()):
for x, pipe in enumerate(row):
p = pipe if pipe != 'S' else s_pipe
for by in range(3):
for bx in range(3):
big_grid[x*3+bx, y*3+by] = expand[p][by][bx]
if pipe == 'S':
big_grid[x*3+1, y*3+1] = 'S'
# print(big_grid)
# print()
big_s_pos = big_grid.find('S')
big_path = find_path(big_grid, big_s_pos)
for pos in big_path:
big_grid[pos] = '@'
# print(big_grid)
def inside(pos: Vec2, *, grid: Grid, fill: str, path: list):
if pos in path:
return False
if not grid.vec2_inside(pos):
return False
if grid[pos] == fill:
return False
return True
inside_func = functools.partial(inside,
grid=big_grid,
path=big_path,
fill='#')
fillcoords = [(0, 0), (width-1, 0), (width-1, height-1), (0, height-1)]
for pos in fillcoords:
big_grid.flood_fill(pos, '#', inside_func)
# print(big_grid)
smol_grid = Grid([[pipe for pipe in row[1::3]] for row in big_grid[1::3]])
# print(smol_grid)
print(sum(sum(1 for pipe in row if pipe not in '@#') for row in smol_grid))