Browse Source

Solve day 20, kinda needs cleanup

Taddeus Kroes 2 năm trước cách đây
mục cha
commit
bef02311d3
2 tập tin đã thay đổi với 120 bổ sung0 xóa
  1. 62 0
      2023/20_pulse.py
  2. 58 0
      2023/input/20

+ 62 - 0
2023/20_pulse.py

@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+import sys
+from collections import deque
+from itertools import count
+from math import lcm
+
+def parse(inp):
+    graph = {}
+    for line in inp:
+        src, dst = line.rstrip().split(' -> ')
+        outputs = dst.split(', ')
+        ty = src[0]
+        if ty in '%&':
+            src = src[1:]
+        prev = graph.get(src, (None, [], None))[1]
+        graph[src] = ty, prev, outputs
+        for out in outputs:
+            graph.setdefault(out, (None, [], []))[1].append(src)
+    return graph
+
+def pulse(graph, flipflops, conjunctions):
+    work = deque([('button', 'broadcaster', False)])
+    while work:
+        prev, node, high = work.popleft()
+        yield node, high
+        ty, inputs, outputs = graph[node]
+        if ty == '%':
+            if not high:
+                flipflops[node] = out = not flipflops.get(node, False)
+                work.extend((node, output, out) for output in outputs)
+        elif ty == '&':
+            state = conjunctions.setdefault(node, {i: False for i in inputs})
+            state[prev] = high
+            out = not all(state.values())
+            work.extend((node, output, out) for output in outputs)
+        else:
+            work.extend((node, output, high) for output in outputs)
+
+def low_high_counts(graph, times):
+    flipflops = {}
+    conjunctions = {}
+    counts = [0, 0]
+    for _ in range(times):
+        for _, high in pulse(graph, flipflops, conjunctions):
+            counts[high] += 1
+    return counts[0] * counts[1]
+
+def pulse_until_rx(graph):
+    flipflops = {}
+    conjunctions = {}
+    sync_nodes = graph[graph['rx'][1][0]][1]
+    periods = {}
+    for presses in count(1):
+        for node, high in pulse(graph, flipflops, conjunctions):
+            if not high and node in sync_nodes:
+                periods[node] = presses
+                if len(periods) == len(sync_nodes):
+                    return lcm(*periods.values())
+
+graph = parse(sys.stdin)
+print(low_high_counts(graph, 1000))
+print(pulse_until_rx(graph))

+ 58 - 0
2023/input/20

@@ -0,0 +1,58 @@
+%ls -> cs, jd
+%st -> jh, bj
+%hc -> tn
+%xs -> rr
+%pq -> tl, cs
+%rj -> km, ck
+%lb -> cg
+%zz -> dx, ch
+%kk -> cs, tc
+%hr -> ck, pl
+%pj -> cs, pr
+%pr -> zl, cs
+%tl -> vn, cs
+%tc -> cs, hn
+&cs -> hn, pj, qb, zl
+%lv -> hr
+%vn -> cs, ls
+&mp -> dr
+broadcaster -> ns, pj, xz, sg
+%gg -> jh, nx
+%cr -> jg, jh
+%ch -> dx
+&dx -> zj, xz, mp, zn, xs, hc
+%fl -> jh, ps
+%hn -> pq
+%qp -> dx, zj
+%bp -> zr
+%kl -> lb
+%pl -> ck, xq
+%rm -> zz, dx
+%rz -> jh, fl
+%pm -> cs, kk
+%zl -> pm
+%rk -> ck, kl
+&dr -> rx
+%cg -> lv, ck
+&qt -> dr
+%jg -> jh
+&qb -> dr
+&ck -> lb, lv, ns, kl, qt
+%zr -> st
+%dd -> dx, qp
+%kd -> rk, ck
+%xq -> rj, ck
+%sg -> rz, jh
+%zj -> hc
+%tn -> dx, xs
+%jd -> cs
+%rr -> rm, dx
+&jh -> ng, bp, zr, sg, bj
+%km -> ck
+%ps -> bp, jh
+%zn -> dd
+%bj -> gg
+%nx -> jh, cr
+%xz -> dx, zn
+&ng -> dr
+%ns -> ck, kd