Advertisement
Guest User

AoC 2024 Day 21 part 2 solution

a guest
Dec 23rd, 2024
455
0
193 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.51 KB | Source Code | 0 0
  1. internal class Solution
  2. {
  3.     private string[] codes;
  4.     private (char c, int x, int y)[] numKeypad;
  5.     private (char c, int x, int y)[] dirKeypad;
  6.  
  7.     public Solution(string test)
  8.     {
  9.         codes = test.Replace("\r\n", "\n").Split('\n');
  10.         numKeypad = (new string[] { "789", "456", "123", " 0A" })
  11.         .SelectMany((row, y) => row.Select((c, x) => (c, x, y)))
  12.         .Where(p => p.c != ' ')
  13.         .ToArray();
  14.         dirKeypad = new string[] { " ^A", "<v>" }
  15.         .SelectMany((row, y) => row.Select((c, x) => (c, x, y)))
  16.         .Where(p => p.c != ' ')
  17.         .ToArray();
  18.     }
  19.     internal string Run()
  20.     {
  21.         var score = 0L;
  22.         var cache = new Dictionary<(char a, char b, int robots), long>();
  23.         foreach (var code in codes)
  24.         {
  25.             var lower = long.MaxValue;
  26.             var moves = NumpadRobotMoves(code, 'A');
  27.             foreach (var move in moves)
  28.             {
  29.                 var pairs = move.Select((c, i) => (a: i == 0 ? 'A' : move[i - 1], b: c)).ToArray();
  30.                 var sum = pairs.Select(p => Cost(p, 25, cache)).Sum();
  31.                 if (sum < lower)
  32.                     lower = sum;
  33.             }
  34.             score += lower * int.Parse(code[..^1]);
  35.         }
  36.         return score.ToString();
  37.     }
  38.     IEnumerable<string> NumpadRobotMoves(string code, char startPosition)
  39.     {
  40.         var end = code[0];
  41.         var moves = Moves(startPosition, end, numKeypad);
  42.         foreach (var move in moves)
  43.             if (code.Length == 1)
  44.                 return moves.Select(m => m + 'A');
  45.             else
  46.                 return moves.SelectMany(m => NumpadRobotMoves(code[1..], end).Select(r => m + 'A' + r));
  47.         return Enumerable.Empty<string>();
  48.     }
  49.  
  50.  
  51.     private long Cost((char a, char b) p, int robots, Dictionary<(char a, char b, int robots), long> cache)
  52.     {
  53.         if (cache.TryGetValue((p.a, p.b, robots), out var inCache))
  54.             return inCache;
  55.         var lower = long.MaxValue;
  56.         var moves = Moves(p.a, p.b, dirKeypad);
  57.         foreach (var move in moves)
  58.         {
  59.             var pairs = move.Append('A').Select((c, i) => (a: i == 0 ? 'A' : move[i - 1], b: c)).ToArray();
  60.             var sum = pairs.Select(p => robots == 1 ? 1 : Cost(p, robots - 1, cache)).Sum();
  61.             if (sum < lower)
  62.                 lower = sum;
  63.         }
  64.         cache.Add((p.a, p.b, robots), lower);
  65.         return lower;
  66.     }
  67.  
  68.     IEnumerable<string> Moves(char start, char end, (char c, int x, int y)[] keypad)
  69.     {
  70.         var res = new List<string>();
  71.         var startp = keypad.First(p => p.c == start);
  72.         var endp = keypad.First(p => p.c == end);
  73.         var stack = new Stack<(int x, int y, List<char> path)>();
  74.         stack.Push((startp.x, startp.y, new List<char>()));
  75.         while (stack.Count > 0)
  76.         {
  77.             var (x, y, path) = stack.Pop();
  78.             if (x == endp.x && y == endp.y)
  79.             {
  80.                 yield return new string(path.ToArray());
  81.                 continue;
  82.             }
  83.             if (!keypad.Any(p => p.x == x && p.y == y))
  84.                 continue;
  85.             if (x < endp.x)
  86.                 stack.Push((x + 1, y, path.Append('>').ToList()));
  87.             if (x > endp.x)
  88.                 stack.Push((x - 1, y, path.Append('<').ToList()));
  89.             if (y < endp.y)
  90.                 stack.Push((x, y + 1, path.Append('v').ToList()));
  91.             if (y > endp.y)
  92.                 stack.Push((x, y - 1, path.Append('^').ToList()));
  93.         }
  94.     }
  95. }
  96.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement