advent_of_code_2023/Day20/python/solution1.py
2023-12-21 22:02:54 +01:00

109 lines
3.2 KiB
Python

from collections import deque
def process_modules(filename, debug=False):
"""
Reads the module configuration from a file, initializes the modules, and simulates the pulse propagation.
Returns the product of total high and low pulses after 1000 button presses.
"""
with open(filename) as f:
lines = f.read().splitlines()
modules = {}
broadcaster = []
for line in lines:
left, right = line.split(" -> ")
destinations = right.split(", ")
if left == "broadcaster":
broadcaster = destinations
continue
module_type = left[0]
module_name = left[1:]
modules[module_name] = [
module_type,
False if module_type == "%" else {},
destinations,
]
# Initialize conjunction modules with False for each input
for name, (_, _, destinations) in modules.items():
for destination in destinations:
if destination in modules and modules[destination][0] == "&":
modules[destination][1][name] = False
low, high = 0, 0
for iteration in range(1000):
queue = deque([("broadcaster", target, False) for target in broadcaster])
while queue:
name, target, pulse = queue.popleft()
if debug:
print(
f"Iteration {iteration}: Processing {target}, Pulse: {'High' if pulse else 'Low'}"
)
if target not in modules:
continue
module = modules[target]
if module[0] == "%":
if pulse:
continue
module[1] = not module[1]
new_pulse = module[1]
else:
module[1][name] = pulse
new_pulse = not all(module[1].values())
for destination in module[2]:
queue.append((target, destination, new_pulse))
# Count pulses when they are sent
if new_pulse:
high += 1
else:
low += 1
if debug:
print(
f"Iteration {iteration}: {target} -> {'High' if new_pulse else 'Low'} to {module[2]}"
)
return low * high
def test():
"""
Runs the process_modules function with the test input and checks if it meets the expected outcome.
"""
expected_result = 11687500 # Replace with the expected result of the test input
test_result = process_modules("../test.txt", debug=True)
assert (
test_result == expected_result
), f"Test failed: Expected {expected_result}, got {test_result}"
print(f"Test passed with result: {test_result}")
def main():
"""
Main function to run the test and then process the actual puzzle input.
"""
try:
print("Running test...")
test()
print("Test passed. Running main input...")
result = process_modules("../input.txt")
print(f"Puzzle result: {result}")
except AssertionError as e:
print(str(e))
print("Stopping execution due to test failure.")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
main()