From c5813e168bd3fcbf29c229b98fa1bccbc890e276 Mon Sep 17 00:00:00 2001 From: felixm Date: Tue, 26 Dec 2023 21:46:55 -0500 Subject: [PATCH] Solve day 20 and day 21 part 1. --- d20.py | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ d21.py | 55 +++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 d20.py create mode 100644 d21.py diff --git a/d20.py b/d20.py new file mode 100644 index 0000000..412fadb --- /dev/null +++ b/d20.py @@ -0,0 +1,108 @@ +from lib import * +from math import lcm + +EXAMPLE = """ +broadcaster -> a, b, c +%a -> b +%b -> c +%c -> inv +&inv -> a +""" + +EXAMPLE2 = """ +broadcaster -> a +%a -> inv, con +&inv -> b +%b -> con +&con -> output +""" + +def visualize(modules): + with open("g20.dot", 'w') as f: + f.write("digraph G {\n") + for m in modules.values(): + for cm in m[3]: + f.write(" " + m[1] + ' -> ' + cm + "\n") + f.write("}") + +def solve(i: Input, second=False): + res = 0 + modules = {} + for line in i.lines(): + if not line: continue + src, dsts = line.split(" -> ") + dsts = dsts.split(", ") + if src.startswith("%"): # flip-flop + modules[src[1:]] = [src[0], src[1:], 0, dsts] + elif src.startswith("&"): # conjunction + modules[src[1:]] = [src[0], src[1:], {}, dsts] + elif src.startswith("broadcaster"): + modules[src] = ["b", src, 0, dsts] + else: + raise Exception() + + for m in modules.values(): + for d in m[3]: + if d in modules and modules[d][0] == "&": + modules[d][2][m[1]] = 0 + + if second: + # visualize(modules) + periods = {d: [] for d in modules["kh"][2].keys()} + BUTTON_PUSHES = 10000 + else: + BUTTON_PUSHES = 1000 + + lo, hi = 0, 0 + for i in range(BUTTON_PUSHES): + qs = [("button module", "broadcaster", 0)] + while qs: + src, dst, sig = qs[0] + qs = qs[1:] + + if sig == 0: + lo += 1 + else: + hi += 1 + + if not dst in modules: + continue + + m = modules[dst] + new_pulse = None + if m[0] == "b": + new_pulse = 0 + elif m[0] == "%": + if sig == 0: + m[2] = (m[2] + 1) % 2 + new_pulse = m[2] + elif m[0] == "&": + m[2][src] = sig + if all(s == 1 for s in m[2].values()): + new_pulse = 0 + else: + new_pulse = 1 + else: + raise Exception() + + if new_pulse is not None: + for nxtdst in m[3]: + if second and nxtdst == "kh" and new_pulse == 1: + # print(f"{i:>4}: {dst[:4]:>4} -{new_pulse}> {nxtdst}") + periods[dst].append(i) + qs.append((dst, nxtdst, new_pulse)) + if second: + # print(periods) + # Yeah, we got a bit lucky that this works, I guess, but it does. + return lcm(*[v[1] - v[0] for v in periods.values()]) + return lo * hi + +def main(): + DAY_INPUT = "i20.txt" + print("Example 1:", solve(Input(EXAMPLE))) + print("Example 2:", solve(Input(EXAMPLE2))) + print("Solution 1:", solve(Input(DAY_INPUT))) + print("Solution 2:", solve(Input(DAY_INPUT), True)) + +if __name__ == "__main__": + main() diff --git a/d21.py b/d21.py new file mode 100644 index 0000000..df7691f --- /dev/null +++ b/d21.py @@ -0,0 +1,55 @@ +from lib import * + +EXAMPLE = """ +........... +.....###.#. +.###.##..#. +..#.#...#.. +....#.#.... +.##..S####. +.##..#...#. +.......##.. +.##.#.####. +.##..##.##. +........... +""" + +def solve(i: Input, second=False): + res = 0 + g = i.grid2() + s = g.find('S')[0] + g[s] = 'O' + # steps = 64 + steps = 26501365 + seen = set() + for i in range(steps): + os = tuple(g.find('O')) + if os in seen: + seen.add(os) + print(f"SEEN {i}") + break + + for o in os: + g[o] = '.' + + for o in os: + for nb in g.neighbors_ort(o): + if not g[nb] == "#": + g[nb] = 'O' + return len(g.find('O')) + +def main(): + DAY_INPUT = "i21.txt" + + print("Example 1:", solve(Input(EXAMPLE))) + print("Solution 1:", solve(Input(DAY_INPUT))) + return + + print("Example 2:", solve(Input(EXAMPLE), True)) + return + + print("Solution 2:", solve(Input(DAY_INPUT), True)) + return + +if __name__ == "__main__": + main()