namespace Day20; public class SignalProcessor { private readonly IDictionary _modules = new Dictionary(); public SignalProcessor(Dictionary modules) { foreach (var kvp in modules) { _modules[kvp.Key] = kvp.Value.m; foreach (var o in kvp.Value.outputs) { Module? dst; if (modules.TryGetValue(o, out var t)) { dst = modules[o].m; } else { _modules.TryAdd(o, new SinkModule(o)); dst = _modules[o]; } kvp.Value.m.AddOutput(dst); dst.AddInput(kvp.Value.m); } } } public HiLo Push(int count) { var visited = new HashSet(); var stateCounts = new List(); var state = MachineState(); var iterations = 0; var result = HiLo.Zero; while (!visited.Contains(state) && iterations < count) { Console.WriteLine(state); visited.Add(state); var hilo = PushTheButton(); stateCounts.Add(hilo); result = result.Add(hilo); state = MachineState(); iterations++; } if (iterations == 0) { throw new InvalidOperationException("WTF?"); } if (iterations < count) { Console.WriteLine($"Cycle @ {iterations} with state {state}"); var cycles = count / iterations; result = result.Multiply(cycles); var remainder = count % iterations; for (var i = 0; i < remainder; i++) { result = result.Add(stateCounts[i]); } } return result; } public HiLo PushTheButton() { var count = HiLo.Zero; var queue = new Queue(); queue.Enqueue(new Pulse("button", "broadcaster", false)); while (queue.Count > 0) { var pulse = queue.Dequeue(); Console.WriteLine($"Sending {pulse.Value} from {pulse.Source} to {pulse.Destination}"); var dst = _modules[pulse.Destination]; count = count.Add(pulse); foreach (var outPulse in dst.Process(pulse)) { queue.Enqueue(outPulse); } } return count; } private string MachineState() { return string.Join("|", _modules.Select(kvp => kvp.Value.GetState())); } }