-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsix.py
135 lines (122 loc) · 3.61 KB
/
six.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
125
126
127
128
129
130
131
132
133
134
135
eg = """....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"""
class LoopError(Exception):
def __init__(self, *args):
super().__init__(*args)
class Guard:
facing: str
x: int
y: int
visited: set
turns: dict
def __init__(self, facing, x, y):
self.facing = facing
self.x = x
self.y = y
self.visited = set()
self.visited.add((y,x))
self.turns = {}
def check(self):
pos = (self.y,self.x)
if pos in self.turns.keys():
if len(self.turns[pos]) > 2:
raise LoopError
self.turns[pos].append(self.facing)
else:
self.turns[pos] = [self.facing]
def walk(guard, grid, debug):
if len(guard.visited) > 0 and debug:
print(f"turning {guard.facing} at ({guard.y},{guard.x}) - visited {len(guard.visited)} spaces")
guard.check()
if guard.facing == "up":
for i in reversed(range(0, guard.y)):
if grid[i][guard.x] == "#":
guard.facing = "right"
return walk(guard, grid, debug)
else:
guard.y = i
guard.visited.add((i, guard.x))
elif guard.facing == "down":
for i in range(guard.y, len(grid)):
if grid[i][guard.x] == "#":
guard.facing = "left"
return walk(guard, grid, debug)
else:
guard.y = i
guard.visited.add((i, guard.x))
elif guard.facing == "right":
for i in range(guard.x, len(grid)):
if grid[guard.y][i] == "#":
guard.facing = "down"
return walk(guard, grid, debug)
else:
guard.x = i
guard.visited.add((guard.y, i))
elif guard.facing == "left":
for i in reversed(range(0, guard.x)):
if grid[guard.y][i] == "#":
guard.facing = "up"
return walk(guard, grid, debug)
else:
guard.x = i
guard.visited.add((guard.y, i))
def one(source, debug):
lines = source.splitlines()
blockers = []
guard = (-1,-1)
for y in range(0, len(lines)):
line = lines[y]
for x in range(0, len(line)):
if line[x] == "^":
guard = Guard(facing="up", x=x, y=y)
elif line[x] == "#":
blockers.append((y,x))
if debug:
print(blockers)
walk(guard, lines, debug)
print(f"guard at ({guard.y},{guard.x}) ({guard.facing}) has visited {len(guard.visited)} spaces")
one(eg, True)
print("---")
with open("six.txt", "r") as file:
one(file.read(), False)
print("---")
def two(source):
lines = source.splitlines()
blockers = []
guard = (-1,-1)
for y in range(0, len(lines)):
line = lines[y]
for x in range(0, len(line)):
if line[x] == "^":
guard = Guard(facing="up", x=x, y=y)
elif line[x] == "#":
blockers.append((y,x))
start = (guard.y, guard.x)
walk(guard, lines, False)
count = 0
nodes = set(guard.visited)
nodes.remove(start)
for y,x in nodes:
grid = lines.copy()
line = grid[y]
grid[y] = line[:x] + '#' + line[x+1:]
try:
guard = Guard(facing="up", x=start[1], y=start[0])
walk(guard, grid, False)
except LoopError:
count += 1
#print(f"obstruction at ({y},{x}) caused loop")
print(f"found {count} loops")
two(eg)
print("---")
with open("six.txt", "r") as file:
two(file.read())