SignalProcessor.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. namespace Day20;
  2. public class SignalProcessor
  3. {
  4. private readonly IDictionary<string, Module> _modules = new Dictionary<string, Module>();
  5. public SignalProcessor(Dictionary<string, (Module m, string[] outputs)> modules)
  6. {
  7. foreach (var kvp in modules)
  8. {
  9. _modules[kvp.Key] = kvp.Value.m;
  10. foreach (var o in kvp.Value.outputs)
  11. {
  12. Module? dst;
  13. if (modules.TryGetValue(o, out var t))
  14. {
  15. dst = modules[o].m;
  16. }
  17. else
  18. {
  19. _modules.TryAdd(o, new SinkModule(o));
  20. dst = _modules[o];
  21. }
  22. kvp.Value.m.AddOutput(dst);
  23. dst.AddInput(kvp.Value.m);
  24. }
  25. }
  26. }
  27. public HiLo Push(int count)
  28. {
  29. var visited = new HashSet<string>();
  30. var stateCounts = new List<HiLo>();
  31. var state = MachineState();
  32. var iterations = 0;
  33. var result = HiLo.Zero;
  34. while (!visited.Contains(state) && iterations < count)
  35. {
  36. Console.WriteLine(state);
  37. visited.Add(state);
  38. var hilo = PushTheButton();
  39. stateCounts.Add(hilo);
  40. result = result.Add(hilo);
  41. state = MachineState();
  42. iterations++;
  43. }
  44. if (iterations == 0)
  45. {
  46. throw new InvalidOperationException("WTF?");
  47. }
  48. if (iterations < count)
  49. {
  50. Console.WriteLine($"Cycle @ {iterations} with state {state}");
  51. var cycles = count / iterations;
  52. result = result.Multiply(cycles);
  53. var remainder = count % iterations;
  54. for (var i = 0; i < remainder; i++)
  55. {
  56. result = result.Add(stateCounts[i]);
  57. }
  58. }
  59. return result;
  60. }
  61. public HiLo PushTheButton()
  62. {
  63. var count = HiLo.Zero;
  64. var queue = new Queue<Pulse>();
  65. queue.Enqueue(new Pulse("button", "broadcaster", false));
  66. while (queue.Count > 0)
  67. {
  68. var pulse = queue.Dequeue();
  69. Console.WriteLine($"Sending {pulse.Value} from {pulse.Source} to {pulse.Destination}");
  70. var dst = _modules[pulse.Destination];
  71. count = count.Add(pulse);
  72. foreach (var outPulse in dst.Process(pulse))
  73. {
  74. queue.Enqueue(outPulse);
  75. }
  76. }
  77. return count;
  78. }
  79. private string MachineState()
  80. {
  81. return string.Join("|", _modules.Select(kvp => kvp.Value.GetState()));
  82. }
  83. }