-
Notifications
You must be signed in to change notification settings - Fork 140
Expand file tree
/
Copy pathd20.py
More file actions
82 lines (64 loc) · 1.94 KB
/
d20.py
File metadata and controls
82 lines (64 loc) · 1.94 KB
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
from collections import namedtuple, defaultdict, deque
class Vector(namedtuple('V2D', ['x', 'y'])):
def __add__(self, other):
return Vector(self.x + other.x, self.y+other.y)
up = Vector(0, 1)
down = Vector(0, -1)
right = Vector(1, 0)
left = Vector(-1, 0)
direction_map = {'N': up, 'S': down, 'E': right, 'W': left}
with open('./20/input.txt') as f:
regex = f.read().strip()[1:-1]
class Graph:
def __init__(self):
self.nodes = set()
self.edges = defaultdict(set)
def add_edge(self, a, b):
for node in [a, b]:
if node not in self.nodes:
self.nodes.add(node)
self.edges[a].add(b)
def bfs(self, start):
q = deque([(start, 0)])
distances = {}
distances[start] = 0
distance = 0
while q:
this, distance = q.pop()
for edge in self.edges[this]:
if edge not in distances:
distances[edge] = distance + 1
q.appendleft((edge, distance+1))
return distances
def parse(regex, graph):
start = Vector(0, 0)
stack = []
fork_results = []
heads = set([start])
for char in regex:
if char == '(':
stack.append(heads)
fork_results.append(set())
elif char == '|':
fork_results[-1].update(heads)
heads = stack[-1]
elif char == ')':
fork_results[-1].update(heads)
heads = fork_results.pop()
stack.pop()
else:
newheads = set()
for head in heads:
newhead = head + direction_map[char]
graph.add_edge(head, newhead)
newheads.add(newhead)
heads = newheads
graph = Graph()
start = Vector(0, 0)
graph = Graph()
parse(regex, graph)
distances = graph.bfs(start)
# p1
print(max(distances.values()))
# p2
print(sum(1 for pos, dist in distances.items() if dist >= 1000))