Skip to content

Commit 2cbd5bb

Browse files
committed
Add solution to 2023-12-20
1 parent 6b1271b commit 2cbd5bb

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

2023/day20/input

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
%vg -> lf, vd
2+
%dr -> kg
3+
%cn -> mv, pt
4+
%rq -> bk, gr
5+
%vp -> lp, bk
6+
%kg -> lv
7+
%lv -> jc, tp
8+
%sj -> rm, vd
9+
%jc -> tp, qr
10+
%km -> tp, dr
11+
%jx -> cn
12+
&vd -> tf, lf, nb, cx, hx, lr
13+
%lp -> jt, bk
14+
%vj -> ps
15+
broadcaster -> km, lr, xh, rf
16+
%dj -> pt, gc
17+
%cg -> vd, hx
18+
&ln -> tg
19+
%fl -> pt, sk
20+
%lm -> tr, bk
21+
%lr -> vd, vg
22+
&pt -> vq, rf, cm, jx, rg
23+
%cx -> gp
24+
%gp -> vd, sj
25+
&db -> tg
26+
%st -> vd
27+
%jt -> bk
28+
%jh -> lm, bk
29+
%xf -> bd, tp
30+
%gc -> cm, pt
31+
&tp -> dr, km, kg, db, vj, qr
32+
%ps -> xf, tp
33+
%rf -> pt, dj
34+
%lf -> nb
35+
%bd -> tp, gg
36+
%dk -> tp, vj
37+
%mn -> jh, bk
38+
&tg -> rx
39+
%ql -> bk, zx
40+
%tr -> bk, vp
41+
%sk -> pt
42+
%nb -> cg
43+
%sb -> vd, cx
44+
%qr -> dk
45+
%xh -> bk, ql
46+
%rg -> sd
47+
%hx -> sb
48+
%sd -> pt, jx
49+
%gr -> bk, mn
50+
%gg -> tp
51+
%zx -> rq
52+
&bk -> xh, ln, zx
53+
%rm -> st, vd
54+
%hq -> fl, pt
55+
&vq -> tg
56+
%cm -> rg
57+
&tf -> tg
58+
%mv -> pt, hq

2023/day20/solutions.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from collections import defaultdict, deque
2+
from itertools import count
3+
from math import lcm, prod
4+
5+
with open("input") as f:
6+
ws = [l.split() for l in f.read().strip().replace(",", "").split("\n")]
7+
8+
flips = {w[1:] for w, *_ in ws if w[0] == "%"}
9+
10+
parents = defaultdict(dict)
11+
children = defaultdict(list)
12+
13+
for w, _, *regs in ws:
14+
for reg in regs:
15+
parents[reg][w.strip("&%")] = False
16+
children[w.strip("&%")].append(reg)
17+
18+
19+
def press_button(states, sent, periods, i):
20+
q = deque([("broadcaster", "button", False)])
21+
22+
def send(sender, signal):
23+
for c in children[sender]:
24+
q.append((c, sender, signal))
25+
26+
while q:
27+
receiver, sender, signal = q.popleft()
28+
sent[signal] += 1
29+
if receiver == "broadcaster":
30+
send("broadcaster", signal)
31+
elif receiver in flips:
32+
if not signal:
33+
states[receiver] = not states[receiver]
34+
send(receiver, states[receiver])
35+
else:
36+
if signal and receiver == "tg" and sender not in periods: # For part 2
37+
periods[sender] = i
38+
parents[receiver][sender] = signal
39+
send(receiver, not all(parents[receiver].values()))
40+
return states, sent, periods
41+
42+
43+
# Part 1
44+
states = defaultdict(bool)
45+
sent = defaultdict(int)
46+
47+
for _ in range(1000):
48+
states, sent, _ = press_button(states, sent, {}, 0)
49+
50+
print(prod(sent.values()))
51+
52+
# Part 2
53+
# For part 2, we manually inspect the output. We find that rx depends only on tg,
54+
# and that tg depends on four other registers. By watching the changes in those,
55+
# we find that they are cyclic, so the earliest time tg could possible be set is
56+
# at a button click count corresponding to the least common multiple of the cycle
57+
# lengths for the four other registers.
58+
states = defaultdict(bool)
59+
sent = defaultdict(int)
60+
periods = {}
61+
62+
for i in count(1):
63+
states, _, periods = press_button(states, sent, periods, i)
64+
if len(periods) == 4:
65+
print(lcm(*periods.values()))
66+
break

0 commit comments

Comments
 (0)