from collections import deque
def visit_nodes(graph, start=0):
queue = deque([start])
seen = {start}
yield start
while queue:
for next_ in graph[queue.popleft()]:
if next_ in seen:
continue
yield next_
seen.add(next_)
queue.append(next_)
def read_graph(lines):
graph = {}
for line in lines:
if not line.strip():
continue
node, targets = line.split(" <-> ")
graph[int(node)] = [int(t) for t in targets.split(",")]
return graph
def graph_groups(graph):
"""yield a node from each group"""
seen = set()
for node in graph:
if node not in seen:
yield node
seen.update(visit_nodes(graph, node))
test_graph = read_graph(
"""\
0 <-> 2
1 <-> 1
2 <-> 0, 3, 4
3 <-> 2, 4
4 <-> 2, 3, 6
5 <-> 6
6 <-> 4, 5
""".splitlines()
)
assert sum(1 for _ in visit_nodes(test_graph)) == 6
assert sum(1 for _ in graph_groups(test_graph)) == 2
import aocd
data = aocd.get_data(day=12, year=2017)
graph = read_graph(data.splitlines())
print("Part 1:", sum(1 for _ in visit_nodes(graph)))
Part 1: 128
print("Part 2:", sum(1 for _ in graph_groups(graph)))
Part 2: 209