// Parse modules relationships
foreach ($input->lines as $line) {
[$_, $type, $name, $dest] = $line->match("/(&|%)?([a-z]+) -> (.+)$/");
$modules[$name] = ["dest" => explode(", ", $dest), "type" => $type];
if ($type === "%") $modules[$name]["flip"] = 0;
if ($type === "&") $modules[$name]["conj"] = [];
foreach (explode(", ", $dest) as $d) $sources[$d][] = $name;
}
// Solve
$counts = [0, 0];
$gates = [$sources[$sources["rx"][0]]][0];
for ($i = 1;; $i++) {
$queue = [["broadcaster", "button", 0]];
while ($queue) {
[$dest, $source, $freq] = array_shift($queue);
$counts[$freq]++;
if (!isset($modules[$dest])) continue;
// Register first time each gate is turned on
if (in_array($dest, $gates) && !$freq) {
$gates_on[$dest] = $i;
if (count($gates_on) == count($gates)) break 2;
}
// Send signals
if ($modules[$dest]["type"] == "&") $modules[$dest]["conj"][$source] = $freq;
$send = match ($modules[$dest]["type"]) {
"%" => (!$freq ? ($modules[$dest]["flip"] = (int) !$modules[$dest]["flip"]) : null),
"&" => array_sum($modules[$dest]["conj"]) == count($sources[$dest]) ? 0 : 1,
default => $freq
};
if ($send !== null) foreach ($modules[$dest]["dest"] as $d) $queue[] = [$d, $dest, $send];
}
if ($i == 1000) $solution_1 = array_product($counts);
}
$solution_2 = array_product($gates_on);