| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- namespace Day16;
- public class Panel
- {
- private readonly Tile[,] _tiles;
- private readonly int _width;
- private readonly int _height;
- private readonly Dictionary<InitialVector, Result> _results = new Dictionary<InitialVector, Result>();
-
- public Panel(Tile[,] tiles)
- {
- _tiles = tiles;
- _width = tiles.GetLength(0);
- _height = tiles.GetLength(1);
- }
- public int Energize(int x, int y, IRay start)
- {
- var result = Energize(new InitialVector(x, y, start));
- Print();
- return result;
- }
- public void MaximizeEnergy()
- {
- var max = 0;
- InitialVector? init = null;
-
- foreach (var v in InitialVectors())
- {
- if (!_results.ContainsKey(v))
- {
- var count = Energize(v);
- if (count > max)
- {
- max = count;
- init = v;
- }
- }
- }
- Console.WriteLine($"Initial Vector: {init?.X} / {init?.Y} => {init?.Ray}");
- Console.WriteLine($"Energized: {max}");
- }
-
- private void Print()
- {
- Console.WriteLine($"{_width} x {_height}");
- for (var y = 0; y < _height; y++)
- {
- for (var x = 0; x < _width; x++)
- {
- Console.Write(_tiles[x, y].IsEnergized ? '#' : _tiles[x, y].Value);
- }
- Console.WriteLine();
- }
- Console.WriteLine();
- }
-
- private int Count()
- {
- var energized = 0;
- for (var y = 0; y < _height; y++)
- {
- for (var x = 0; x < _width; x++)
- {
- energized += _tiles[x, y].IsEnergized ? 1 : 0;
- _tiles[x, y].Clear();
- }
- }
- return energized;
- }
-
- private int Energize(InitialVector vector)
- {
- var tile = _tiles[vector.X, vector.Y];
- var stack = new Stack<(IRay Ray, Tile Tile)>();
- stack.Push((vector.Ray, tile));
- var result = new Result();
- _results[vector] = result;
- while (stack.Count > 0)
- {
- var item = stack.Pop();
- foreach (var r in item.Tile.Process(item.Ray))
- {
- var next = Next(r, item.Tile);
- if (next == null)
- {
- var equivalentInitialVector = new InitialVector(item.Tile.X, item.Tile.Y, r.Rotate().Rotate());
- _results[equivalentInitialVector] = result;
- }
- else
- {
- stack.Push((r, next));
- }
- }
- }
- result.Energized = Count();
- return result.Energized;
- }
- private Tile? Next(IRay ray, Tile tile)
- {
- var (x, y) = ray.Apply(tile);
- return x >= 0 && x < _width && y >= 0 && y < _height
- ? _tiles[x, y]
- : null;
- }
- private IEnumerable<InitialVector> InitialVectors()
- {
- for (var x = 0; x < _width; x++)
- {
- yield return new InitialVector(x, 0, Rays.South);
- yield return new InitialVector(x, _height - 1, Rays.North);
- }
- for (var y = 0; y < _height; y++)
- {
- yield return new InitialVector(0, y, Rays.East);
- yield return new InitialVector(_width - 1, y, Rays.West);
- }
- }
- private record InitialVector(int X, int Y, IRay Ray);
- private class Result
- {
- public int Energized { get; set; }
- public IList<InitialVector> InitialVectors { get; } = new List<InitialVector>();
- }
- }
|