using System.Text; namespace Day10; public class Grid { private readonly int _width; private readonly int _height; private Tile? _start; public Tile[,] Tiles { get; } public Grid(Tile[,] tiles, int width, int height) { _width = width; _height = height; Tiles = tiles; } public void Print() { for (var y = 0; y < _height; y++) { var lineBuilder = new StringBuilder(); for (var x = 0; x < _width; x++) { lineBuilder.Append(Tiles[x, y].Display ?? " "); } Console.WriteLine(lineBuilder); } } public int Follow() { foreach (var t in Tiles) { if (t.Pipe == 'S') { _start = t; break; } } if (_start == null) { throw new Exception("Start is not set yet"); } var queue = new Queue<(Tile Tile, GridPoint Source, int Index)>(); queue.Enqueue((_start, _start.Position, 0)); while (queue.Count > 0) { var (tile, source, index) = queue.Dequeue(); if (tile.HasDisplay) { UpdateStart(); return index; } foreach (var next in tile.GetConnections() .Where(n => n != source) .Select(x => this[x]) .Where(t => t?.ConnectsTo(tile.Position) ?? false)) { queue.Enqueue((next!, tile.Position, index + 1)); } tile.SetDisplay(index); } throw new Exception("No cycle found"); } public int Enclosed() { var enclosed = 0; for (var y = 0; y < _height; y++) { var verticals = 0; var half = 0; for (var x = 0; x < _width; x++) { var tile = Tiles[x, y]; if (!tile.HasDisplay) { enclosed += (verticals % 2 == 1) ? 1 : 0; } else { switch (tile.Pipe) { case '|': verticals++; break; case 'F': case '7': half += 1; if (half == 0) { verticals++; } break; case 'J': case 'L': half -= 1; if (half == 0) { verticals++; } break; default: break; } if (Math.Abs(half) > 1) { half = 0; } } } } return enclosed; } public Tile? this[GridPoint point] { get { if (point.X < 0 || point.Y < 0 || point.X >= _width || point.Y >= _height) { return null; } return Tiles[point.X, point.Y]; } } private void UpdateStart() { var outlets = _start! .GetConnections() .Select(p => this[p]) .Where(t => (t?.HasDisplay ?? false) && (t.ConnectsTo(_start.Position))) .Cast() .ToList(); if (outlets.Count != 2) { throw new Exception("Only 2 outlets for S expected"); } var east = outlets.Any(t => t.Position.X > _start.Position.X); var west = outlets.Any(t => t.Position.X < _start.Position.X); var north = outlets.Any(t => t.Position.Y < _start.Position.Y); var south = outlets.Any(t => t.Position.Y > _start.Position.Y); var pipe = ' '; if (north && south) { pipe = '|'; } if (north && east) { pipe = 'L'; } if (north && west) { pipe = 'J'; } if (east && west) { pipe = '-'; } if (south && east) { pipe = 'F'; } if (south && west) { pipe = '7'; } Tiles[_start.Position.X, _start.Position.Y] = new Tile(pipe, _start.Position); _start = Tiles[_start.Position.X, _start.Position.Y]; _start.SetDisplay(0); } }