namespace Day21; public class Map { private readonly int _width; private readonly int _height; private readonly Tile[,] _map; private readonly Tile? _start; public Map(int width, int height, IEnumerable tiles) { _width = width; _height = height; _map = new Tile[width, height]; var i = 0; foreach (var t in tiles) { if (t.IsStart) { _start = t; } t.Position = new Vec(i % width, i / width); _map[t.Position.X, t.Position.Y] = t; i++; } if (_start == null) { throw new Exception("No start tile found"); } } public void Print(ISet? mark = null) { for (int y = 0; y < _height; y++) { for (int x = 0; x < _width; x++) { if (mark != null && mark.Contains(new Vec(x, y))) { Console.Write('O'); } else { Console.Write(_map[x, y]); } } Console.WriteLine(); } Console.WriteLine(); } public long ReachableTiles(int steps) { var reachable = new HashSet(); reachable.Add(_start!.Position); for (int i = 0; i < steps; i++) { var next = new HashSet(); foreach (var p in reachable) { foreach (var neighbor in Surrounding(p).Where(n => At(n)?.IsWalkable ?? false)) { next.Add(neighbor); } } reachable = next; } Print(reachable); return reachable.Count; } private IEnumerable Surrounding(Vec middle) { yield return middle.Add(ScreenSpace.Up); yield return middle.Add(ScreenSpace.Right); yield return middle.Add(ScreenSpace.Down); yield return middle.Add(ScreenSpace.Left); } private Tile? At(Vec p) { if (p.X < 0 || p.X >= _width || p.Y < 0 || p.Y >= _height) { return null; } return _map[p.X, p.Y]; } }