Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #load "xunit"
- #load "..\AOC Connector"
- void Main(string[] args)
- {
- if(args == null)
- RunTests(); // Call RunTests() or press Alt+Shift+T to initiate testing.
- //get aoc data
- var aoc = new AdventOfCode(2020, 22);
- //solve A
- aoc.SubmitAnswer(SolveA(aoc.InputLines), Part.A);
- //solve B
- aoc.SubmitAnswer(SolveB(aoc.InputLines), Part.B);
- }
- int SolveA(string[] data)
- {
- //parse input
- var p1 = new Queue<int>(data.Skip(1).TakeWhile(x => x != "").Select(x => int.Parse(x)));
- var p2 = new Queue<int>(data.SkipWhile(x => x != "").Skip(2).Select(x => int.Parse(x)));
- //play the game
- var winner = Play(p1, p2, false);
- //calculate answer
- return winner.windata.Reverse().Select((x, i) => x * (i+1)).Sum();
- }
- long SolveB(string[] data)
- {
- //parse data
- var p1 = new Queue<int>(data.Skip(1).TakeWhile(x => x != "").Select(x => int.Parse(x)));
- var p2 = new Queue<int>(data.SkipWhile(x => x != "").Skip(2).Select(x => int.Parse(x)));
- //determine winner
- var winner = Play(p1, p2, true);
- //calc score
- return winner.windata.Reverse().Select((x, i) => x * (i + 1L)).Sum();
- }
- (int winner, Queue<int> windata) Play(IEnumerable<int> p1Source, IEnumerable<int> p2Source, bool recursive)
- {
- //keep track of the decks played
- var decksPlayed = new HashSet<string>();
- //create new queues
- var player1 = new Queue<int>(p1Source);
- var player2 = new Queue<int>(p2Source);
- //play while any player has cards
- while (player1.Any() && player2.Any())
- {
- //draw cards
- var cardPlayer1 = player1.Dequeue();
- var cardPlayer2 = player2.Dequeue();
- //determine winner
- var target = cardPlayer1 > cardPlayer2 ? player1 : player2;
- //are we player recursive variant
- if (recursive)
- {
- //recursive
- if (cardPlayer1 <= player1.Count && cardPlayer2 <= player2.Count && (player1.Count + player2.Count > 1))
- {
- //start new game
- if (Play(player1.Take(cardPlayer1), player2.Take(cardPlayer2), true).winner == 1)
- target = player1;
- else
- target = player2;
- }
- }
- //give the winner the cards
- if(target == player1)
- {
- player1.Enqueue(cardPlayer1);
- player1.Enqueue(cardPlayer2);
- }
- else
- {
- player2.Enqueue(cardPlayer2);
- player2.Enqueue(cardPlayer1);
- }
- //infinite loop check
- //create a key
- var key = $"{string.Join(",", player1.ToArray())}";
- //if already seen, player 1 wins
- if(decksPlayed.Contains(key)) return (1, player1);
- //add current state to the hashset
- decksPlayed.Add(key);
- }
- //return the winner, and their deck
- return (player1.Any() ? 1 : 2, player1.Any() ? player1 : player2);
- }
- // You can define other methods, fields, classes and namespaces here
- #region private::Tests
- //test data
- string[] testdata = new[]
- {
- "Player 1:",
- "9",
- "2",
- "6",
- "3",
- "1",
- "",
- "Player 2:",
- "5",
- "8",
- "4",
- "7",
- "10",
- };
- //tests
- [Fact] void TestA() => Assert.Equal(306, SolveA(testdata));
- [Fact] void TestB() => Assert.Equal(291, SolveB(testdata));
- #endregion
Add Comment
Please, Sign In to add comment