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}")