Commit c8328076 authored by Germain Clavier's avatar Germain Clavier 😺
Browse files

Added solution for day 8

parent 6f02d21b
Loading
Loading
Loading
Loading

2023/day8/code.py

0 → 100644
+99 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
Solution of day 8 of 2023
'''

import time
import argparse as ap
import re
import math
from itertools import cycle


def solve1(file=None, verbose=False, solution=0):
    try:
        expr = re.compile(r"\W+")
        mymap = {}
        with open(file, 'r') as f:
            data = f.read().split('\n\n')
        instructions = data[0]
        nodes = data[1].split('\n')
        for n in nodes[:-1]:
            info = expr.split(n)
            mymap[info[0]] = {"L": info[1], "R": info[2]}
        current = 'AAA'
        instructions = cycle(instructions)
        while current != 'ZZZ':
            solution += 1
            go = next(instructions)
            current = mymap[current][go]

    except FileNotFoundError:
        pass

    return solution

def solve2(file=None, verbose=False, solution=0):
    try:
        expr = re.compile(r"\W+")
        mymap = {}
        starts = []
        end = []
        with open(file, 'r') as f:
            data = f.read().split('\n\n')
        instructions = data[0]
        instructions = cycle(instructions)

        nodes = data[1].split('\n')
        for n in nodes[:-1]:
            info = expr.split(n)
            if info[0][2] == 'A':
                starts.append(info[0])
            mymap[info[0]] = {"L": info[1], "R": info[2]}
        # The trick is actually that all the paths are rather short loops (less
        # than 100k steps) but they should all end on there Z label *at the
        # same time*. The first time this happens is our puzzle answer, and the
        # LCM of all the individual loops.
        # Note that given that there are two examples in this puzzle, this
        # solution will not work on the test set.
        for start in starts:
            for step, go in enumerate(instructions, start=1):
                start = mymap[start][go]
                if start[2] == 'Z':
                    end.append(step)
                    break
        return math.lcm(*end)

    except FileNotFoundError:
        pass

    return solution

def main():
    parser = ap.ArgumentParser()
    parser.add_argument('-i', dest='input', action='store_true')
    parser.add_argument('-v', dest='verbose', action='store_true')
    args = parser.parse_args()
    infile = 'input' if args.input else 'test'
    verbose = args.verbose

    t0 = time.time()
    sol1 = solve1(infile, verbose)
    dt = time.time() - t0
    print(f"Solution 1: {sol1}, Time: {dt}")

    t0 = time.time()
    sol2 = solve2(infile, verbose)
    dt = time.time() - t0
    print(f"Solution 2: {sol2}, Time: {dt}")

    return


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        raise SystemExit("User interruption.")

2023/day8/test

0 → 100644
+9 −0
Original line number Diff line number Diff line
RL

AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)