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()
