Untitled
unknown
python
a year ago
2.9 kB
3
Indexable
from advent_of_code.lib import parse as aoc_parse from advent_of_code.lib import aoc from dataclasses import dataclass, field from collections import defaultdict, deque from abc import ABC @dataclass class Message: sender: str user: str signal: int @dataclass class Module(ABC): name: str links: list[str] = field(default_factory=list) def receive(self, sender, signal, q): pass def send(self, signal, q): for link in self.links: q.append(Message(self.name, link, signal)) @dataclass class FlipFlop(Module): value: int = 0 def receive(self, sender, signal, q): if signal == 0: self.value = 1 - self.value self.send(self.value, q) class Conjunction(Module): def set_pre(self, pre): self.pre = {p: 0 for p in pre} def receive(self, sender, signal, q): self.pre[sender] = signal self.send(0 if all(self.pre.values()) else 1, q) class Broadcaster(Module): def receive(self, sender, signal, q): pass class Output(Module): def send(self, signal, q): pass def get_module(config): name, links = config.split(" -> ") links = list(links.split(", ")) if name == "broadcaster": return Broadcaster(name, links) if name[0] == "%": return FlipFlop(name[1:], links) if name[0] == "&": return Conjunction(name[1:], links) def get_input(file): raw = aoc.read_input(2023, 20, file) modules = {} for line in aoc_parse.as_lines(raw): module = get_module(line) modules[module.name] = module # compute predecessors of conjuctions pre = defaultdict(list) for name, module in modules.items(): for link in module.links: pre[link].append(name) for name, module in modules.items(): if isinstance(module, Conjunction): module.set_pre(pre[name]) # add output nodes for module in list(modules.values()): for link in module.links: if link not in modules: modules[link] = Output(link) return modules @aoc.pretty_solution(1) def part1(modules): low_pulse, high_pulse = 0, 0 for _ in range(1000): # manually handle the queue of messages q = deque() modules["broadcaster"].send(0, q) while q: msg = q.popleft() low_pulse += msg.signal == 0 high_pulse += msg.signal == 1 # process this message # the module that receives it will update the q modules[msg.user].receive(msg.sender, msg.signal, q) return (low_pulse + 1000) * high_pulse if __name__ == "__main__": data = get_input("input.txt") part1(data)
Editor is loading...
Leave a Comment