69 lines
1.7 KiB
Python
69 lines
1.7 KiB
Python
import shared
|
|
from scanf import scanf
|
|
from pprint import pprint
|
|
from math import lcm
|
|
|
|
|
|
def setup(rows):
|
|
MAP = {}
|
|
instructions = rows.pop(0)
|
|
rows.pop(0)
|
|
instructions = instructions.replace("L", "0")
|
|
instructions = instructions.replace("R", "1")
|
|
instructions = [int(x) for x in instructions]
|
|
|
|
for row in rows:
|
|
entry, left, right = scanf("%s = (%s, %s)", row)
|
|
MAP[entry] = [left, right]
|
|
return MAP, instructions
|
|
|
|
|
|
# @shared.profile
|
|
def part1(rows):
|
|
_map, _instructions = setup(rows)
|
|
count, _ = find("AAA", _instructions, _map)
|
|
print(count)
|
|
|
|
|
|
# @shared.profile
|
|
def part2(rows):
|
|
_map, _instructions = setup(rows)
|
|
starting_points = [k for k in _map.keys() if k[-1] == "A"]
|
|
ending_points = [k for k in _map.keys() if k[-1] == "Z"]
|
|
ends = []
|
|
for s in starting_points:
|
|
count, end = find(s, _instructions, _map, None)
|
|
ends.append(count)
|
|
print(lcm(*ends))
|
|
|
|
|
|
def find(start, instructions, MAP, target="ZZZ"):
|
|
count = 0
|
|
current = start
|
|
while True:
|
|
idx = count % len(instructions)
|
|
l_r = instructions[idx]
|
|
current = MAP[current][l_r]
|
|
count += 1
|
|
if target is None:
|
|
if current.endswith("Z"):
|
|
return count, current
|
|
elif current == target:
|
|
return count, current
|
|
|
|
|
|
def main():
|
|
rows = [row for row in shared.load_rows(8)]
|
|
with shared.elapsed_timer() as elapsed:
|
|
part1(rows[:])
|
|
print("🕒", elapsed())
|
|
|
|
rows = [row for row in shared.load_rows(8, True)]
|
|
with shared.elapsed_timer() as elapsed:
|
|
part2(rows[:])
|
|
print("🕒", elapsed())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|