Map.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. namespace Day21;
  2. public class Map
  3. {
  4. private readonly int _width;
  5. private readonly int _height;
  6. private readonly Tile[,] _map;
  7. private readonly Tile? _start;
  8. public Map(int width, int height, IEnumerable<Tile> tiles)
  9. {
  10. _width = width;
  11. _height = height;
  12. _map = new Tile[width, height];
  13. var i = 0;
  14. foreach (var t in tiles)
  15. {
  16. if (t.IsStart)
  17. {
  18. _start = t;
  19. }
  20. t.Position = new Vec(i % width, i / width);
  21. _map[t.Position.X, t.Position.Y] = t;
  22. i++;
  23. }
  24. if (_start == null)
  25. {
  26. throw new Exception("No start tile found");
  27. }
  28. }
  29. public void Print(ISet<Vec>? mark = null)
  30. {
  31. for (int y = 0; y < _height; y++)
  32. {
  33. for (int x = 0; x < _width; x++)
  34. {
  35. if (mark != null && mark.Contains(new Vec(x, y)))
  36. {
  37. Console.Write('O');
  38. }
  39. else
  40. {
  41. Console.Write(_map[x, y]);
  42. }
  43. }
  44. Console.WriteLine();
  45. }
  46. Console.WriteLine();
  47. }
  48. public long ReachableTiles(int steps)
  49. {
  50. var reachable = new HashSet<Vec>();
  51. reachable.Add(_start!.Position);
  52. for (int i = 0; i < steps; i++)
  53. {
  54. var next = new HashSet<Vec>();
  55. foreach (var p in reachable)
  56. {
  57. foreach (var neighbor in Surrounding(p).Where(n => At(n)?.IsWalkable ?? false))
  58. {
  59. next.Add(neighbor);
  60. }
  61. }
  62. reachable = next;
  63. }
  64. Print(reachable);
  65. return reachable.Count;
  66. }
  67. private IEnumerable<Vec> Surrounding(Vec middle)
  68. {
  69. yield return middle.Add(ScreenSpace.Up);
  70. yield return middle.Add(ScreenSpace.Right);
  71. yield return middle.Add(ScreenSpace.Down);
  72. yield return middle.Add(ScreenSpace.Left);
  73. }
  74. private Tile? At(Vec p)
  75. {
  76. if (p.X < 0 || p.X >= _width || p.Y < 0 || p.Y >= _height)
  77. {
  78. return null;
  79. }
  80. return _map[p.X, p.Y];
  81. }
  82. }