You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.5 KiB
90 lines
2.5 KiB
lines = open('inputs/day8.txt').readlines()
|
|
|
|
class Node():
|
|
def __init__(self, name, l, r):
|
|
self.name = name
|
|
self.l = l
|
|
self.r = r
|
|
|
|
def parse_nodes(lines: str) -> dict:
|
|
nodes = {}
|
|
for i in range(2, len(lines)):
|
|
line = lines[i].split('=')
|
|
name = line[0].strip()
|
|
ns = line[1].strip().strip('\n').strip('(').strip(')').split(',')
|
|
l = ns[0].strip()
|
|
r = ns[1].strip()
|
|
nodes[name] = Node(name, l, r)
|
|
return nodes
|
|
|
|
def all_zs_reached(nodes: list[str]) -> bool:
|
|
for node in nodes:
|
|
if node[2] != "Z":
|
|
return False
|
|
return True
|
|
|
|
def traverse_nodes(nodes: list[str], start: str = "AAA", ghost: bool = False) -> int:
|
|
instructions = lines[0].strip("\n")
|
|
found = False
|
|
counter = 0
|
|
curr = nodes[start]
|
|
while not found:
|
|
for instr in instructions:
|
|
if ghost:
|
|
if curr.name[2] == "Z":
|
|
found = True
|
|
break
|
|
if curr.name == "ZZZ":
|
|
found = True
|
|
break
|
|
if instr == 'L':
|
|
curr = nodes[curr.l]
|
|
else:
|
|
curr = nodes[curr.r]
|
|
counter += 1
|
|
return counter
|
|
|
|
nodes = parse_nodes(lines)
|
|
print(f"Solution Part 1: {traverse_nodes(nodes)}")
|
|
|
|
def traverse_nodes_ghost(nodes: list[str]) -> int:
|
|
instructions = lines[0].strip("\n")
|
|
found = False
|
|
counter = 0
|
|
currs = [node for node in nodes if node[2] == "A"]
|
|
while not found:
|
|
for instr in instructions:
|
|
if all_zs_reached(currs):
|
|
found = True
|
|
break
|
|
if instr == 'L':
|
|
currs = [nodes[c].l for c in currs]
|
|
else:
|
|
currs = [nodes[c].r for c in currs]
|
|
counter += 1
|
|
return counter
|
|
|
|
def traverse_all_XXA(nodes: list[str]) -> list[int]:
|
|
currs = [node for node in nodes if node[2] == "A"]
|
|
steps = []
|
|
for curr in currs:
|
|
steps.append(traverse_nodes(nodes, curr, True))
|
|
return steps
|
|
|
|
# lcm of multiple numbers stolen from https://stackoverflow.com/questions/147515/least-common-multiple-for-3-or-more-numbers
|
|
def gcd(a, b):
|
|
"""Return greatest common divisor using Euclid's Algorithm."""
|
|
while b:
|
|
a, b = b, a % b
|
|
return a
|
|
|
|
def lcm(a, b):
|
|
"""Return lowest common multiple."""
|
|
return a * b // gcd(a, b)
|
|
|
|
steps = traverse_all_XXA(nodes)
|
|
x = steps[0]
|
|
for i in range(1, len(steps)):
|
|
x = lcm(x, steps[i])
|
|
|
|
print(f"Solution Part 2: {x}") |