-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday6.py
104 lines (96 loc) · 3 KB
/
day6.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
import copy
import textwrap
def part1(input: str) -> int:
(maze, pos) = parse(input)
visited = { pos }
directions = (
(-1, 0), (0, 1), (1, 0), (0, -1)
)
dir_i = 0
while True:
direction = directions[dir_i]
next = (pos[0] + direction[0], pos[1] + direction[1])
if next[0] >= len(maze) or next[1] >= len(maze[0]):
return len(visited)
if maze[next[0]][next[1]] == '#':
dir_i += 1
if dir_i >= len(directions):
dir_i = 0
else:
pos = next
visited.add(pos)
def part2(input: str) -> int:
(maze, start_pos) = parse(input)
directions = (
(-1, 0), (0, 1), (1, 0), (0, -1)
)
def full_path(maze, start_pos, dir_i):
pos = start_pos
visited = set()
while True:
visited.add((pos, dir_i))
direction = directions[dir_i]
next = (pos[0] + direction[0], pos[1] + direction[1])
if next[0] >= len(maze) or next[0] < 0 or next[1] >= len(maze[0]) or next[1] < 0:
return {
"path": visited,
"is_loop": False
}
if (next, dir_i) in visited:
return {
"path": visited,
"is_loop": True
}
if maze[next[0]][next[1]] == '#':
dir_i += 1
if dir_i >= len(directions):
dir_i = 0
else:
pos = next
# fills potential_loops
all_visited = full_path(maze, start_pos, 0)["path"]
# print("Potential loops:", len(all_visited))
loops = set()
for (pos, dir_i) in all_visited:
if pos == start_pos:
continue
maze_with_block = copy.deepcopy(maze)
maze_with_block[pos[0]][pos[1]] = '#'
if full_path(maze_with_block, start_pos, 0)["is_loop"]:
# print(f"Loop detected {pos}, {direction}")
loops.add(pos)
# sys.stdout.write(".")
return len(loops)
def parse(input: str):
lines = input.splitlines()
result = []
start = None
for (y, line) in enumerate(lines):
result.append([])
for (x, char) in enumerate(line):
if char == "^":
start = (y, x)
result[y].append(".")
else:
result[y].append(char)
return (result, start)
if __name__ == "__main__":
test_input = textwrap.dedent("""
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"""
).strip()
input = open('day6.txt').read()
print("Part 1 test, 41 expected: %s" % part1(test_input))
print("Part 1: %s" % part1(input))
print("Part 2 test, 6 expected: %s" % part2(test_input))
# print("Part 2 time (100x): %s" % timeit.timeit(lambda: part2(test_input), number=100))
print("Part 2: %s" % part2(input))