Equd

AOC 2020 Day 22

Dec 22nd, 2020 (edited)
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.99 KB | None | 0 0
  1. #load "xunit"
  2. #load "..\AOC Connector"
  3.  
  4. void Main(string[] args)
  5. {
  6.     if(args == null)
  7.         RunTests();  // Call RunTests() or press Alt+Shift+T to initiate testing.
  8.  
  9.     //get aoc data
  10.     var aoc = new AdventOfCode(2020, 22);
  11.    
  12.     //solve A
  13.     aoc.SubmitAnswer(SolveA(aoc.InputLines), Part.A);
  14.  
  15.     //solve B
  16.     aoc.SubmitAnswer(SolveB(aoc.InputLines), Part.B);
  17. }
  18.  
  19.  
  20.  
  21. int SolveA(string[] data)
  22. {
  23.     //parse input
  24.     var p1 = new Queue<int>(data.Skip(1).TakeWhile(x => x != "").Select(x => int.Parse(x)));
  25.     var p2 = new Queue<int>(data.SkipWhile(x => x != "").Skip(2).Select(x => int.Parse(x)));
  26.  
  27.     //play the game
  28.     var winner = Play(p1, p2, false);
  29.  
  30.     //calculate answer
  31.     return winner.windata.Reverse().Select((x, i) => x * (i+1)).Sum();
  32. }
  33. long SolveB(string[] data)
  34. {
  35.     //parse data
  36.     var p1 = new Queue<int>(data.Skip(1).TakeWhile(x => x != "").Select(x => int.Parse(x)));
  37.     var p2 = new Queue<int>(data.SkipWhile(x => x != "").Skip(2).Select(x => int.Parse(x)));
  38.  
  39.     //determine winner
  40.     var winner = Play(p1, p2, true);
  41.  
  42.     //calc score
  43.     return winner.windata.Reverse().Select((x, i) => x * (i + 1L)).Sum();
  44. }
  45.  
  46.  
  47. (int winner, Queue<int> windata) Play(IEnumerable<int> p1Source, IEnumerable<int> p2Source, bool recursive)
  48. {
  49.     //keep track of the decks played
  50.     var decksPlayed = new HashSet<string>();
  51.    
  52.     //create new queues
  53.     var player1 = new Queue<int>(p1Source);
  54.     var player2 = new Queue<int>(p2Source);        
  55.    
  56.     //play while any player has cards
  57.     while (player1.Any() && player2.Any())
  58.     {      
  59.         //draw cards
  60.         var cardPlayer1 = player1.Dequeue();
  61.         var cardPlayer2 = player2.Dequeue();
  62.        
  63.         //determine winner
  64.         var target = cardPlayer1 > cardPlayer2 ? player1 : player2;    
  65.  
  66.         //are we player recursive variant
  67.         if (recursive)
  68.         {
  69.             //recursive
  70.             if (cardPlayer1 <= player1.Count && cardPlayer2 <= player2.Count && (player1.Count + player2.Count > 1))
  71.             {
  72.                 //start new game
  73.                 if (Play(player1.Take(cardPlayer1), player2.Take(cardPlayer2), true).winner == 1)
  74.                     target = player1;
  75.                 else
  76.                     target = player2;
  77.             }
  78.         }
  79.    
  80.         //give the winner the cards
  81.         if(target == player1)
  82.         {
  83.             player1.Enqueue(cardPlayer1);
  84.             player1.Enqueue(cardPlayer2);
  85.         }
  86.         else
  87.         {
  88.             player2.Enqueue(cardPlayer2);
  89.             player2.Enqueue(cardPlayer1);
  90.         }
  91.  
  92.  
  93.         //infinite loop check
  94.         //create a key
  95.         var key = $"{string.Join(",", player1.ToArray())}";
  96.        
  97.         //if already seen, player 1 wins
  98.         if(decksPlayed.Contains(key)) return (1, player1);
  99.        
  100.         //add current state to the hashset
  101.         decksPlayed.Add(key);
  102.     }
  103.  
  104.     //return the winner, and their deck
  105.     return (player1.Any() ? 1 : 2, player1.Any() ? player1 : player2);
  106. }
  107.  
  108. // You can define other methods, fields, classes and namespaces here
  109.  
  110. #region private::Tests
  111. //test data
  112. string[] testdata = new[]
  113. {
  114. "Player 1:",
  115. "9",
  116. "2",
  117. "6",
  118. "3",
  119. "1",
  120. "",
  121. "Player 2:",
  122. "5",
  123. "8",
  124. "4",
  125. "7",
  126. "10",
  127. };
  128.  
  129. //tests
  130. [Fact] void TestA() => Assert.Equal(306, SolveA(testdata));
  131. [Fact] void TestB() => Assert.Equal(291, SolveB(testdata));
  132.  
  133. #endregion
Add Comment
Please, Sign In to add comment