| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- 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<Tile>()
- .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);
- }
- }
|