Advertisement
mgla

Advent of Code 2023 - Day 16

Dec 16th, 2023 (edited)
861
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.11 KB | None | 0 0
  1. using System.Diagnostics;
  2.  
  3. var input = File.ReadAllLines("input.txt").Select(l => l.ToCharArray()).ToArray();
  4. var timer = Stopwatch.StartNew();
  5.  
  6. Console.WriteLine($"Part 1: {CountTiles(input, 0, -1, Directions.Right)}, Elapsed: {timer.ElapsedMilliseconds}ms");
  7.  
  8. timer.Restart();
  9. var tasks = new List<Task<int>>();
  10.  
  11. for (var row = 0; row < input.Length; row++)
  12. {
  13.     var currentRow = row;
  14.     tasks.Add(Task.Run(() => CountTiles(input, currentRow, -1, Directions.Right)));
  15.     tasks.Add(Task.Run(() => CountTiles(input, currentRow, input[currentRow].Length, Directions.Left)));
  16. }
  17.  
  18. for (var col = 0; col < input[0].Length; col++)
  19. {
  20.     var currentCol = col;
  21.     tasks.Add(Task.Run(() => CountTiles(input, -1, currentCol, Directions.Down)));
  22.     tasks.Add(Task.Run(() => CountTiles(input, input.Length, currentCol, Directions.Up)));
  23. }
  24.  
  25. await Task.WhenAll(tasks);
  26.  
  27. Console.WriteLine($"Part 2: {tasks.Max(t => t.Result)}, Elapsed: {timer.ElapsedMilliseconds}ms");
  28. return;
  29.  
  30. static int CountTiles(char[][] map, int startRow, int startColumn, Directions startDirection)
  31. {
  32.     var tiles = new Dictionary<(int row, int col), Directions>
  33.     {
  34.         [(startRow, startColumn)] = Directions.None // Add the entry point which is outside the map
  35.     };
  36.  
  37.     var beams = new Queue<(int Row, int Column, Directions Direction)>();
  38.     beams.Enqueue((startRow, startColumn, startDirection));
  39.  
  40.     while (beams.TryDequeue(out var beam))
  41.     {
  42.         if (tiles.TryGetValue((beam.Row, beam.Column), out var tileDirections) &&
  43.             tileDirections.HasFlag(beam.Direction))
  44.         {
  45.             continue;
  46.         }
  47.  
  48.         tiles[(beam.Row, beam.Column)] = tileDirections | beam.Direction;
  49.  
  50.         var (row, col) = beam.Direction switch
  51.         {
  52.             Directions.Up => (beam.Row - 1, beam.Column),
  53.             Directions.Down => (beam.Row + 1, beam.Column),
  54.             Directions.Left => (beam.Row, beam.Column - 1),
  55.             Directions.Right => (beam.Row, beam.Column + 1),
  56.             _ => throw new Exception("Invalid direction")
  57.         };
  58.  
  59.         if (row < 0 || row >= map.Length || col < 0 || col >= map[row].Length)
  60.         {
  61.             continue;
  62.         }
  63.  
  64.         beam = beam with { Row = row, Column = col };
  65.  
  66.         switch (map[row][col])
  67.         {
  68.             case '/':
  69.                 beams.Enqueue(beam with
  70.                 {
  71.                     Direction = beam.Direction switch
  72.                     {
  73.                         Directions.Up => Directions.Right,
  74.                         Directions.Down => Directions.Left,
  75.                         Directions.Left => Directions.Down,
  76.                         Directions.Right => Directions.Up,
  77.                         _ => throw new Exception("Invalid direction")
  78.                     }
  79.                 });
  80.                 break;
  81.             case '\\':
  82.                 beams.Enqueue(beam with
  83.                 {
  84.                     Direction = beam.Direction switch
  85.                     {
  86.                         Directions.Up => Directions.Left,
  87.                         Directions.Down => Directions.Right,
  88.                         Directions.Left => Directions.Up,
  89.                         Directions.Right => Directions.Down,
  90.                         _ => throw new Exception("Invalid direction")
  91.                     }
  92.                 });
  93.                 break;
  94.             case '-' when beam.Direction is Directions.Up or Directions.Down:
  95.                 beams.Enqueue(beam with { Direction = Directions.Left });
  96.                 beams.Enqueue(beam with { Direction = Directions.Right });
  97.                 break;
  98.             case '|' when beam.Direction is Directions.Left or Directions.Right:
  99.                 beams.Enqueue(beam with { Direction = Directions.Up });
  100.                 beams.Enqueue(beam with { Direction = Directions.Down });
  101.                 break;
  102.             default: // '.', '-' or '|' in the same direction
  103.                 beams.Enqueue(beam);
  104.                 break;
  105.         }
  106.     }
  107.  
  108.     return tiles.Count - 1;
  109. }
  110.  
  111. [Flags]
  112. internal enum Directions
  113. {
  114.     None = 0,
  115.     Up = 1,
  116.     Down = 2,
  117.     Left = 4,
  118.     Right = 8
  119. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement