generated from public/aoc_template
Day 20
This commit is contained in:
parent
c0ffc5a8df
commit
d1a6dbe4bc
151
day20.py
Normal file
151
day20.py
Normal file
@ -0,0 +1,151 @@
|
||||
from __future__ import annotations
|
||||
import math
|
||||
from collections import defaultdict, deque
|
||||
from tools.aoc import AOCDay
|
||||
from typing import Any
|
||||
|
||||
|
||||
class Module:
|
||||
def __init__(self, name: str, machine: Machine):
|
||||
self.name = name
|
||||
self.machine = machine
|
||||
self.state = False
|
||||
self.last_input = defaultdict(bool)
|
||||
self.inputs = []
|
||||
self.outputs = []
|
||||
|
||||
def add_output(self, output: str):
|
||||
self.outputs.append(output)
|
||||
|
||||
def add_input(self, input: str):
|
||||
self.inputs.append(input)
|
||||
|
||||
def send(self, signal: bool):
|
||||
self.state = signal
|
||||
for output in self.outputs:
|
||||
self.machine.send(self.name, output, signal)
|
||||
|
||||
def receive(self, sender: str, signal: bool):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Broadcaster(Module):
|
||||
def receive(self, sender: str, signal: bool):
|
||||
self.send(signal)
|
||||
|
||||
|
||||
class FlipFlop(Module):
|
||||
def receive(self, sender: str, signal: bool):
|
||||
if not signal:
|
||||
self.send(not self.state)
|
||||
|
||||
|
||||
class Conjunction(Module):
|
||||
def receive(self, sender: str, signal: bool):
|
||||
self.last_input[sender] = signal
|
||||
if sum(self.last_input.values()) == len(self.inputs):
|
||||
self.send(False)
|
||||
else:
|
||||
self.send(True)
|
||||
|
||||
|
||||
class Machine:
|
||||
def __init__(self):
|
||||
self.queue = deque()
|
||||
self.send_signals = {
|
||||
True: 0, False: 0
|
||||
}
|
||||
self.modules = {}
|
||||
|
||||
def add_module(self, module: Module):
|
||||
self.modules[module.name] = module
|
||||
|
||||
def update_connections(self):
|
||||
modules = list(self.modules.values())
|
||||
for module in modules:
|
||||
module.inputs = []
|
||||
|
||||
for module in modules:
|
||||
for output in module.outputs:
|
||||
if output not in self.modules:
|
||||
self.modules[output] = FlipFlop(output, self)
|
||||
self.modules[output].add_input(module.name)
|
||||
|
||||
def send(self, sender: str, destination: str, signal: bool):
|
||||
self.queue.append((sender, destination, signal))
|
||||
|
||||
def push_button(self, monitor: str = None):
|
||||
self.send('button', 'broadcaster', False)
|
||||
monitor_highs = []
|
||||
while self.queue:
|
||||
sender, destination, signal = self.queue.popleft()
|
||||
if destination == monitor and signal:
|
||||
monitor_highs.append(sender)
|
||||
self.send_signals[signal] += 1
|
||||
self.modules[destination].receive(sender, signal)
|
||||
|
||||
return monitor_highs
|
||||
|
||||
def get_signal_value(self) -> int:
|
||||
return self.send_signals[True] * self.send_signals[False]
|
||||
|
||||
|
||||
class Day(AOCDay):
|
||||
inputs = [
|
||||
[
|
||||
(32000000, "input20_test"),
|
||||
(11687500, "input20_test2"),
|
||||
(1020211150, "input20"),
|
||||
],
|
||||
[
|
||||
(238815727638557, "input20"),
|
||||
]
|
||||
]
|
||||
|
||||
def parse_input(self) -> Machine:
|
||||
machine = Machine()
|
||||
for line in self.getInput():
|
||||
module_name, targets = line.split(" -> ")
|
||||
if module_name.startswith("broad"):
|
||||
module = Broadcaster(module_name, machine)
|
||||
elif module_name.startswith("%"):
|
||||
module = FlipFlop(module_name[1:], machine)
|
||||
elif module_name.startswith("&"):
|
||||
module = Conjunction(module_name[1:], machine)
|
||||
else:
|
||||
assert False, "unknown module type: %s" % module_name
|
||||
|
||||
for target in targets.split(", "):
|
||||
module.add_output(target)
|
||||
|
||||
machine.add_module(module)
|
||||
|
||||
machine.update_connections()
|
||||
return machine
|
||||
|
||||
def part1(self) -> Any:
|
||||
machine = self.parse_input()
|
||||
for _ in range(1000):
|
||||
machine.push_button()
|
||||
return machine.get_signal_value()
|
||||
|
||||
def part2(self) -> Any:
|
||||
machine = self.parse_input()
|
||||
count = 0
|
||||
input_highs = {}
|
||||
to_monitor = machine.modules["rx"].inputs[0]
|
||||
wait_for = len(machine.modules[to_monitor].inputs)
|
||||
while True:
|
||||
count += 1
|
||||
found_highs = machine.push_button(monitor=to_monitor)
|
||||
|
||||
for high in found_highs:
|
||||
input_highs[high] = count
|
||||
|
||||
if len(input_highs) == wait_for:
|
||||
return math.lcm(*list(input_highs.values()))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
day = Day(2023, 20)
|
||||
day.run(verbose=True)
|
||||
58
inputs/input20
Normal file
58
inputs/input20
Normal file
@ -0,0 +1,58 @@
|
||||
%ls -> gl
|
||||
%rz -> vm, gl
|
||||
broadcaster -> rz, fp, kv, fd
|
||||
%ql -> bn
|
||||
%bm -> hr, fj
|
||||
%fp -> cc, gk
|
||||
&lk -> nc
|
||||
%xg -> gl, mz
|
||||
%dg -> gk, mp
|
||||
%zg -> ls, gl
|
||||
%lg -> hr
|
||||
%pt -> lg, hr
|
||||
%sp -> mj
|
||||
%ms -> gl, hx
|
||||
%kj -> fl, gk
|
||||
%bn -> rj, gk
|
||||
%xc -> vq
|
||||
%fl -> gk
|
||||
%dh -> hr, nm
|
||||
%jk -> gk, dg
|
||||
%tf -> cb
|
||||
%kd -> cm, nr
|
||||
&hr -> hh, kv, xl, qq
|
||||
%kv -> xr, hr
|
||||
%hq -> ql
|
||||
&fn -> nc
|
||||
%vm -> gl, xn
|
||||
%jh -> nr, kd
|
||||
%mz -> dd
|
||||
%tp -> hq
|
||||
%cf -> nr
|
||||
%gr -> jh
|
||||
%jd -> hr, bm
|
||||
%xr -> qq, hr
|
||||
%cm -> nr, cf
|
||||
&fh -> nc
|
||||
%rb -> xl, hr
|
||||
&nc -> rx
|
||||
%mp -> gk, kj
|
||||
&nr -> fd, gr, fn, cb, tf, xc, vq
|
||||
&gl -> fh, xn, sp, mz, rz, mj, dd
|
||||
%rj -> jk
|
||||
&hh -> nc
|
||||
%fd -> nr, df
|
||||
&gk -> lk, tp, fp, ql, hq, rj
|
||||
%fj -> pt, hr
|
||||
%qq -> dh
|
||||
%df -> nr, nv
|
||||
%mj -> ms
|
||||
%xn -> xg
|
||||
%cc -> gk, tp
|
||||
%nm -> rb, hr
|
||||
%dd -> sp
|
||||
%vq -> gr
|
||||
%cb -> xc
|
||||
%nv -> tf, nr
|
||||
%xl -> jd
|
||||
%hx -> gl, zg
|
||||
5
inputs/input20_test
Normal file
5
inputs/input20_test
Normal file
@ -0,0 +1,5 @@
|
||||
broadcaster -> a, b, c
|
||||
%a -> b
|
||||
%b -> c
|
||||
%c -> inv
|
||||
&inv -> a
|
||||
5
inputs/input20_test2
Normal file
5
inputs/input20_test2
Normal file
@ -0,0 +1,5 @@
|
||||
broadcaster -> a
|
||||
%a -> inv, con
|
||||
&inv -> b
|
||||
%b -> con
|
||||
&con -> output
|
||||
Loading…
Reference in New Issue
Block a user