Skip to content

Commit

Permalink
Add solution to 2023-12-20
Browse files Browse the repository at this point in the history
  • Loading branch information
fuglede committed Dec 20, 2023
1 parent aa1bb70 commit 649e33e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
58 changes: 58 additions & 0 deletions 2023/day20/input
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
%vg -> lf, vd
%dr -> kg
%cn -> mv, pt
%rq -> bk, gr
%vp -> lp, bk
%kg -> lv
%lv -> jc, tp
%sj -> rm, vd
%jc -> tp, qr
%km -> tp, dr
%jx -> cn
&vd -> tf, lf, nb, cx, hx, lr
%lp -> jt, bk
%vj -> ps
broadcaster -> km, lr, xh, rf
%dj -> pt, gc
%cg -> vd, hx
&ln -> tg
%fl -> pt, sk
%lm -> tr, bk
%lr -> vd, vg
&pt -> vq, rf, cm, jx, rg
%cx -> gp
%gp -> vd, sj
&db -> tg
%st -> vd
%jt -> bk
%jh -> lm, bk
%xf -> bd, tp
%gc -> cm, pt
&tp -> dr, km, kg, db, vj, qr
%ps -> xf, tp
%rf -> pt, dj
%lf -> nb
%bd -> tp, gg
%dk -> tp, vj
%mn -> jh, bk
&tg -> rx
%ql -> bk, zx
%tr -> bk, vp
%sk -> pt
%nb -> cg
%sb -> vd, cx
%qr -> dk
%xh -> bk, ql
%rg -> sd
%hx -> sb
%sd -> pt, jx
%gr -> bk, mn
%gg -> tp
%zx -> rq
&bk -> xh, ln, zx
%rm -> st, vd
%hq -> fl, pt
&vq -> tg
%cm -> rg
&tf -> tg
%mv -> pt, hq
66 changes: 66 additions & 0 deletions 2023/day20/solutions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from collections import defaultdict, deque
from itertools import count
from math import lcm, prod

with open("input") as f:
ws = [l.split() for l in f.read().strip().replace(",", "").split("\n")]

flips = {w[1:] for w, *_ in ws if w[0] == "%"}

parents = defaultdict(dict)
children = defaultdict(list)

for w, _, *regs in ws:
for reg in regs:
parents[reg][w.strip("&%")] = False
children[w.strip("&%")].append(reg)


def press_button(states, sent, periods, i):
q = deque([("broadcaster", "button", False)])

def send(sender, signal):
for c in children[sender]:
q.append((c, sender, signal))

while q:
receiver, sender, signal = q.popleft()
sent[signal] += 1
if receiver == "broadcaster":
send("broadcaster", signal)
elif receiver in flips:
if not signal:
states[receiver] = not states[receiver]
send(receiver, states[receiver])
else:
if signal and receiver == "tg" and sender not in periods: # For part 2
periods[sender] = i
parents[receiver][sender] = signal
send(receiver, not all(parents[receiver].values()))
return states, sent, periods


# Part 1
states = defaultdict(bool)
sent = defaultdict(int)

for _ in range(1000):
states, sent, _ = press_button(states, sent, {}, 0)

print(prod(sent.values()))

# Part 2
# For part 2, we manually inspect the output. We find that rx depends only on tg,
# and that tg depends on four other registers. By watching the changes in those,
# we find that they are cyclic, so the earliest time tg could possible be set is
# at a button click count corresponding to the least common multiple of the cycle
# lengths for the four other registers.
states = defaultdict(bool)
sent = defaultdict(int)
periods = {}

for i in count(1):
states, _, periods = press_button(states, sent, periods, i)
if len(periods) == 4:
print(lcm(*periods.values()))
break

0 comments on commit 649e33e

Please sign in to comment.