114 lines
2.7 KiB
Python
114 lines
2.7 KiB
Python
import sys
|
|
from collections import defaultdict, deque
|
|
import math
|
|
|
|
with open(r'advent_of_code\2023\20\input.txt', 'r') as file:
|
|
input = file.read()
|
|
|
|
test_input = r'''broadcaster -> a, b, c
|
|
%a -> b
|
|
%b -> c
|
|
%c -> inv
|
|
&inv -> a'''
|
|
|
|
another_test_input = r'''broadcaster -> a
|
|
%a -> inv, con
|
|
&inv -> b
|
|
%b -> con
|
|
&con -> output'''
|
|
|
|
# input = test_input
|
|
# input = another_test_input
|
|
|
|
# Read input
|
|
input_data = input
|
|
lines = input_data.split('\n')
|
|
|
|
# Function to calculate least common multiple
|
|
def least_common_multiple(numbers):
|
|
result = 1
|
|
for num in numbers:
|
|
result = (result * num) // math.gcd(num, result)
|
|
return result
|
|
|
|
# Initialize dictionaries
|
|
type_dict = {}
|
|
rules_dict = {}
|
|
|
|
# Parse input lines
|
|
for line in lines:
|
|
source, destination = line.split('->')
|
|
source = source.strip()
|
|
destination = destination.strip().split(', ')
|
|
rules_dict[source] = destination
|
|
type_dict[source[1:]] = source[0]
|
|
|
|
# Function to adjust type
|
|
def adjust_type(type):
|
|
if type in type_dict:
|
|
return type_dict[type] + type
|
|
else:
|
|
return type
|
|
|
|
# Initialize more dictionaries
|
|
from_dict = {}
|
|
inverse_dict = defaultdict(list)
|
|
|
|
# Adjust types and fill dictionaries
|
|
for x, ys in rules_dict.items():
|
|
rules_dict[x] = [adjust_type(y) for y in ys]
|
|
for y in rules_dict[x]:
|
|
if y[0] == '&':
|
|
if y not in from_dict:
|
|
from_dict[y] = {}
|
|
from_dict[y][x] = 'lo'
|
|
inverse_dict[y].append(x)
|
|
|
|
# Initialize variables
|
|
watch = inverse_dict[inverse_dict['rx'][0]]
|
|
low_count = 0
|
|
high_count = 0
|
|
queue = deque()
|
|
on_set = set()
|
|
previous_dict = {}
|
|
count_dict = defaultdict(int)
|
|
to_lcm = []
|
|
|
|
# Main loop
|
|
for timestamp in range(1, 1001):
|
|
queue.append(('broadcaster', 'button', 'lo'))
|
|
|
|
while queue:
|
|
x, from_, typ = queue.popleft()
|
|
|
|
if typ == 'lo':
|
|
low_count += 1
|
|
else:
|
|
high_count += 1
|
|
|
|
if x not in rules_dict:
|
|
continue
|
|
if x == 'broadcaster':
|
|
for y in rules_dict[x]:
|
|
queue.append((y, x, typ))
|
|
elif x[0] == '%':
|
|
if typ == 'hi':
|
|
continue
|
|
else:
|
|
if x not in on_set:
|
|
on_set.add(x)
|
|
new_typ = 'hi'
|
|
else:
|
|
on_set.discard(x)
|
|
new_typ = 'lo'
|
|
for y in rules_dict[x]:
|
|
queue.append((y, x, new_typ))
|
|
elif x[0] == '&':
|
|
from_dict[x][from_] = typ
|
|
new_typ = ('lo' if all(y == 'hi' for y in from_dict[x].values()) else 'hi')
|
|
for y in rules_dict[x]:
|
|
queue.append((y, x, new_typ))
|
|
else:
|
|
assert False, x
|
|
if timestamp == 1000:
|
|
print(low_count * high_count) |