|
|
@@ -0,0 +1,79 @@ |
|
|
|
import math |
|
|
|
|
|
|
|
|
|
|
|
def send(parent, sender, signal): |
|
|
|
match kinds[sender], signal: |
|
|
|
case 'rx' | 'output', _: |
|
|
|
signal = None |
|
|
|
case 'button' | 'broadcaster', _: |
|
|
|
pass |
|
|
|
case '%', 0: |
|
|
|
signal = state[sender] = int(not state[sender]) |
|
|
|
case '%', 1: |
|
|
|
signal = None |
|
|
|
case '&', _: |
|
|
|
state[sender][parent] = signal |
|
|
|
seen = set(state[sender].values()) |
|
|
|
signal = 0 if seen == {1} else 1 |
|
|
|
case default: |
|
|
|
raise RuntimeError(default) |
|
|
|
|
|
|
|
if signal is not None: |
|
|
|
for target in targets[sender]: |
|
|
|
# print(sender, signal, target) |
|
|
|
output.append(signal) |
|
|
|
yield (sender, target, signal) |
|
|
|
|
|
|
|
|
|
|
|
def deps(p): |
|
|
|
seen = set() |
|
|
|
state = {p} |
|
|
|
while state: |
|
|
|
seen |= state |
|
|
|
state = {k for p in state for k, vs in targets.items() if p in vs and k not in seen} |
|
|
|
return tuple(sorted(seen)) |
|
|
|
|
|
|
|
|
|
|
|
text = open(0).read() |
|
|
|
targets = {'button': ['broadcaster']} |
|
|
|
kinds = {'button': 'button', 'rx': 'rx', 'output': 'output'} |
|
|
|
for line in text.splitlines(): |
|
|
|
src, dst = line.split(' -> ') |
|
|
|
dst = dst.split(', ') |
|
|
|
if src == 'broadcaster': |
|
|
|
label = kind = 'broadcaster' |
|
|
|
else: |
|
|
|
label, kind = src[1:], src[0] |
|
|
|
targets[label] = dst |
|
|
|
kinds[label] = kind |
|
|
|
state = {} |
|
|
|
state |= {l: 0 for l, k in kinds.items() if k == '%'} |
|
|
|
state |= {l: {i: 0 for i, ts in targets.items() if l in ts} for l, k in kinds.items() if k == '&'} |
|
|
|
|
|
|
|
families = {} |
|
|
|
for k in kinds: |
|
|
|
families.setdefault(hash(deps(k)), []).append(k) |
|
|
|
families = {tuple(vs): set() for vs in families.values() if len(vs) > 1} |
|
|
|
|
|
|
|
seq = [] |
|
|
|
seen = set() |
|
|
|
while True: |
|
|
|
output = [] |
|
|
|
active = [(None, 'button', 0)] |
|
|
|
while active: |
|
|
|
active = [new for old in active for new in send(*old)] |
|
|
|
seq.append(output) |
|
|
|
|
|
|
|
before = [len(vs) for vs in families.values()] |
|
|
|
for ks in families: |
|
|
|
families[ks].add(hash(str([state[k] for k in ks]))) |
|
|
|
after = [len(vs) for vs in families.values()] |
|
|
|
if before == after: |
|
|
|
break |
|
|
|
|
|
|
|
if len(seq) == 1000: |
|
|
|
# pt 1 |
|
|
|
los = [sum(v == 0 for v in vs) for vs in seq] |
|
|
|
his = [sum(v == 1 for v in vs) for vs in seq] |
|
|
|
print(sum(los[i % len(los)] for i in range(1000)) * sum(his[i % len(his)] for i in range(1000))) |
|
|
|
print(math.prod(after)) |