Panel.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. namespace Day16;
  2. public class Panel
  3. {
  4. private readonly Tile[,] _tiles;
  5. private readonly int _width;
  6. private readonly int _height;
  7. private readonly Dictionary<InitialVector, Result> _results = new Dictionary<InitialVector, Result>();
  8. public Panel(Tile[,] tiles)
  9. {
  10. _tiles = tiles;
  11. _width = tiles.GetLength(0);
  12. _height = tiles.GetLength(1);
  13. }
  14. public int Energize(int x, int y, IRay start)
  15. {
  16. var result = Energize(new InitialVector(x, y, start));
  17. Print();
  18. return result;
  19. }
  20. public void MaximizeEnergy()
  21. {
  22. var max = 0;
  23. InitialVector? init = null;
  24. foreach (var v in InitialVectors())
  25. {
  26. if (!_results.ContainsKey(v))
  27. {
  28. var count = Energize(v);
  29. if (count > max)
  30. {
  31. max = count;
  32. init = v;
  33. }
  34. }
  35. }
  36. Console.WriteLine($"Initial Vector: {init?.X} / {init?.Y} => {init?.Ray}");
  37. Console.WriteLine($"Energized: {max}");
  38. }
  39. private void Print()
  40. {
  41. Console.WriteLine($"{_width} x {_height}");
  42. for (var y = 0; y < _height; y++)
  43. {
  44. for (var x = 0; x < _width; x++)
  45. {
  46. Console.Write(_tiles[x, y].IsEnergized ? '#' : _tiles[x, y].Value);
  47. }
  48. Console.WriteLine();
  49. }
  50. Console.WriteLine();
  51. }
  52. private int Count()
  53. {
  54. var energized = 0;
  55. for (var y = 0; y < _height; y++)
  56. {
  57. for (var x = 0; x < _width; x++)
  58. {
  59. energized += _tiles[x, y].IsEnergized ? 1 : 0;
  60. _tiles[x, y].Clear();
  61. }
  62. }
  63. return energized;
  64. }
  65. private int Energize(InitialVector vector)
  66. {
  67. var tile = _tiles[vector.X, vector.Y];
  68. var stack = new Stack<(IRay Ray, Tile Tile)>();
  69. stack.Push((vector.Ray, tile));
  70. var result = new Result();
  71. _results[vector] = result;
  72. while (stack.Count > 0)
  73. {
  74. var item = stack.Pop();
  75. foreach (var r in item.Tile.Process(item.Ray))
  76. {
  77. var next = Next(r, item.Tile);
  78. if (next == null)
  79. {
  80. var equivalentInitialVector = new InitialVector(item.Tile.X, item.Tile.Y, r.Rotate().Rotate());
  81. _results[equivalentInitialVector] = result;
  82. }
  83. else
  84. {
  85. stack.Push((r, next));
  86. }
  87. }
  88. }
  89. result.Energized = Count();
  90. return result.Energized;
  91. }
  92. private Tile? Next(IRay ray, Tile tile)
  93. {
  94. var (x, y) = ray.Apply(tile);
  95. return x >= 0 && x < _width && y >= 0 && y < _height
  96. ? _tiles[x, y]
  97. : null;
  98. }
  99. private IEnumerable<InitialVector> InitialVectors()
  100. {
  101. for (var x = 0; x < _width; x++)
  102. {
  103. yield return new InitialVector(x, 0, Rays.South);
  104. yield return new InitialVector(x, _height - 1, Rays.North);
  105. }
  106. for (var y = 0; y < _height; y++)
  107. {
  108. yield return new InitialVector(0, y, Rays.East);
  109. yield return new InitialVector(_width - 1, y, Rays.West);
  110. }
  111. }
  112. private record InitialVector(int X, int Y, IRay Ray);
  113. private class Result
  114. {
  115. public int Energized { get; set; }
  116. public IList<InitialVector> InitialVectors { get; } = new List<InitialVector>();
  117. }
  118. }