Dag: 20
SprÄk: Python
Har haft klar separation mellan del 1 och del 2 alla andra dagar, men blev tillrÀckligt mycket enklare att köra bÄda samtidigt för att göra ett avsteg denna gÄng...
from collections import deque
from math import lcm
def parse_configuration(input):
modules, inputs = {}, {}
for line in input.split("\n"):
action, targets = line.split(" -> ")
outs = targets.split(", ")
modules[action] = outs
for out in outs:
action = action[1:] if action[0] in "&%" else action
inputs[out] = inputs.get(out, []) + [action]
config = {}
for action, targets in modules.items():
if action[0] == "%": # flip-flop {action: [target, STATE]}
config[action[1:]] = [targets, False]
elif action[0] == "&": # conjunction {action: [target, {INPUTS_NAME_TO_STATE}]}
config[action[1:]] = [targets, {input: False for input in inputs[action[1:]]}]
else: # broadcaster
config[action] = [targets, None]
return config
def push_button(config, numButtonPresses, rxFanInFirstFalsePulses):
pendingPulses = deque()
pendingPulses.append(("button", False, "broadcaster"))
lowPulses, highPules = 0, 0
while pendingPulses:
sender, inLevel, action = pendingPulses.popleft()
if inLevel:
highPules += 1
else:
lowPulses += 1
if action not in config:
continue
outputs, state = config[action]
if state is None: # broadcaster
outLevel = inLevel
elif isinstance(state, bool): # flip-flop
if inLevel is False:
outLevel = not state
config[action][1] = outLevel
else:
continue
else: # conjunction
state[sender] = inLevel
outLevel = not all(state.values())
if inLevel and "rx" in outputs and sender not in rxFanInFirstFalsePulses:
rxFanInFirstFalsePulses[sender] = numButtonPresses
for output in outputs:
pendingPulses.append((action, outLevel, output))
return lowPulses, highPules
def run_config(config):
lowPulses, highPules = 0, 0
buttonPresses = 0
rxFanInFirstFalsePulses = {}
while len(rxFanInFirstFalsePulses) < 4:
buttonPresses += 1
pulses = push_button(config, buttonPresses, rxFanInFirstFalsePulses)
if buttonPresses <= 1000:
lowPulses += pulses[0]
highPules += pulses[1]
return lowPulses * highPules, lcm(*rxFanInFirstFalsePulses.values())
def solve(input):
config = parse_configuration(input)
pulseProduct, minButtonPresses = run_config(config)
print(pulseProduct)
print(minButtonPresses)
if __name__ == "__main__":
solve(open("input/day20.txt").read())
Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer