advent-of-code/2023/day8/day8.py

76 lines
2.5 KiB
Python
Raw Permalink Normal View History

2024-12-03 14:29:02 +00:00
import re
import math
from itertools import cycle
def parse_input(infile):
with open(infile) as f:
content = f.read().rstrip()
directions, nodes = content.split("\n\n")
directions = directions.strip()
nodes = nodes.split("\n")
nodes = [n.split(" = ") for n in nodes]
nodes = {k: re.findall(r"\w{3}", v) for k, v in nodes}
return directions, nodes
def part1(directions, nodes):
iterations = 0
current_node = "AAA"
for d in cycle(directions):
if current_node == "ZZZ":
break
iterations += 1
if d == "L":
current_node = nodes[current_node][0]
else:
current_node = nodes[current_node][1]
print(f"Part 1: reached 'ZZZ' in {iterations} iterations")
def part2(directions, nodes):
current_nodes = [k for k in nodes.keys() if k.endswith("A")]
# keep track of iterations number for each visited node
# (the number will stop to beeing incremented once the node n_i value reached the target value 'xxZ')
iterations = [0] * len(current_nodes)
for d in cycle(directions):
if all(c.endswith("Z") for c in current_nodes):
break
if d == "L":
new_nodes = []
for i, n in enumerate(current_nodes):
if n.endswith("Z"): # end condition already reached for this node
new_nodes.append(n)
else:
new_nodes.append(nodes[n][0])
iterations[i] += 1
current_nodes = new_nodes
else:
new_nodes = []
for i, n in enumerate(current_nodes):
if n.endswith("Z"): # end condition already reached for this node
new_nodes.append(n)
else:
new_nodes.append(nodes[n][1])
iterations[i] += 1
current_nodes = new_nodes
# the result is the lowest common multiple between the number of iterations
# for each node
result = math.lcm(*iterations)
print(f"Part 2: reached all nodes such that 'xxZ' in {result} iterations")
if __name__ == "__main__":
import sys
import os
SCRIPTPATH = os.path.dirname(os.path.realpath(__file__))
infile = sys.argv[1] if len(sys.argv) == 2 else "example.txt"
directions, nodes = parse_input(os.path.join(SCRIPTPATH, infile))
part1(directions, nodes)
directions, nodes = parse_input(os.path.join(SCRIPTPATH, infile))
part2(directions, nodes)