From 03e94085029b13ed8b2d54183d4fdb7852d25648 Mon Sep 17 00:00:00 2001 From: Parnic Date: Tue, 22 Dec 2020 08:45:47 -0600 Subject: [PATCH] Day 22 refactor - 2-3x speedup from changing infinite lookup method This new method fixes the hands-seen-before check to be actually correct Unsure how I got the correct answers with that being wrong. :shrug: --- Extensions.cs | 18 +++++++ Q22.cs | 139 +++++++++++++++++++++++--------------------------- 2 files changed, 83 insertions(+), 74 deletions(-) create mode 100644 Extensions.cs diff --git a/Extensions.cs b/Extensions.cs new file mode 100644 index 0000000..18d6fef --- /dev/null +++ b/Extensions.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace _2020 +{ + public static class Extensions + { + public static T PopFront(this ICollection list) + { + T val = list.First(); + list.Remove(val); + return val; + } + } +} diff --git a/Q22.cs b/Q22.cs index 446885a..322f3f6 100644 --- a/Q22.cs +++ b/Q22.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; @@ -46,42 +45,25 @@ namespace _2020 } } - static void Part1() + static string MakeHandsGUID(IEnumerable p1deck, IEnumerable p2deck) { - var p1deck = new List(list[1]); - var p2deck = new List(list[2]); - while (p1deck.Any() && p2deck.Any()) - { - var p1card = p1deck.First(); - p1deck.RemoveAt(0); - var p2card = p2deck.First(); - p2deck.RemoveAt(0); - if (p1card > p2card) - { - p1deck.Add(p1card); - p1deck.Add(p2card); - } - else - { - p2deck.Add(p2card); - p2deck.Add(p1card); - } - } + return string.Join(",", string.Join("-", p1deck), string.Join("-", p2deck)); + } - var winner = p1deck.Count == 0 ? p2deck : p1deck; - var score = 0; - for (int i = winner.Count - 1; i >= 0; i--) - { - score += (i + 1) * winner[winner.Count - i - 1]; - } + static void HandleRoundWinner(bool p1Wins, ICollection p1deck, ICollection p2deck, int p1card, int p2card) + { + var deck = p1Wins ? p1deck : p2deck; + var firstCard = p1Wins ? p1card : p2card; + var secondCard = p1Wins ? p2card : p1card; - Util.Log($"Q22Part1: score={score}"); + deck.Add(firstCard); + deck.Add(secondCard); } static int gameNum = 0; static int deepestLevel = 0; static int currLevel = 0; - static int PlayRecursiveGame(List p1deck, List p2deck) + static int PlayGame(ICollection p1deck, ICollection p2deck, bool recursiveGame = false) { gameNum++; currLevel++; @@ -90,50 +72,39 @@ namespace _2020 deepestLevel = currLevel; } - var p1prev = new List>(); - var p2prev = new List>(); + Dictionary prevHands = null; while (p1deck.Any() && p2deck.Any()) { - if (p1prev.Any(x => Enumerable.SequenceEqual(p1deck, x)) && p2prev.Any(x => Enumerable.SequenceEqual(p2deck, x))) + if (recursiveGame) { - currLevel--; - return 1; + if (prevHands == null) + { + prevHands = new Dictionary(); + } + + var guid = MakeHandsGUID(p1deck, p2deck); + if (prevHands.ContainsKey(guid)) + { + currLevel--; + return 1; + } + + prevHands.Add(guid, true); } - p1prev.Add(new List(p1deck)); - p2prev.Add(new List(p2deck)); + var p1card = p1deck.PopFront(); + var p2card = p2deck.PopFront(); + if (recursiveGame) + { + if (p1deck.Count >= p1card && p2deck.Count >= p2card) + { + var winner = PlayGame(new List(p1deck.Take(p1card)), new List(p2deck.Take(p2card)), recursiveGame); + HandleRoundWinner(winner == 1, p1deck, p2deck, p1card, p2card); + continue; + } + } - var p1card = p1deck.First(); - p1deck.RemoveAt(0); - var p2card = p2deck.First(); - p2deck.RemoveAt(0); - if (p1deck.Count >= p1card && p2deck.Count >= p2card) - { - var winner = PlayRecursiveGame(new List(p1deck.Take(p1card)), new List(p2deck.Take(p2card))); - if (winner == 1) - { - p1deck.Add(p1card); - p1deck.Add(p2card); - } - else - { - p2deck.Add(p2card); - p2deck.Add(p1card); - } - } - else - { - if (p1card > p2card) - { - p1deck.Add(p1card); - p1deck.Add(p2card); - } - else - { - p2deck.Add(p2card); - p2deck.Add(p1card); - } - } + HandleRoundWinner(p1card > p2card, p1deck, p2deck, p1card, p2card); } currLevel--; @@ -141,18 +112,38 @@ namespace _2020 return p1deck.Any() ? 1 : 2; } - static void Part2() + static int GetScore(IEnumerable winnerDeck) { - var winner = PlayRecursiveGame(list[1], list[2]); - var score = 0; - var winnerDeck = list[winner]; - for (int i = winnerDeck.Count - 1; i >= 0; i--) + var deckSize = winnerDeck.Count(); + var idx = 0; + foreach (var card in winnerDeck) { - score += (i + 1) * winnerDeck[winnerDeck.Count - i - 1]; + score += (deckSize - idx) * card; + idx++; } - Util.Log($"Q22Part2: games played={gameNum}, deepest level={deepestLevel}, score={score}"); + return score; + } + + static void Part1() + { + var p1deck = new List(list[1]); + var p2deck = new List(list[2]); + var winner = PlayGame(p1deck, p2deck); + var score = GetScore(winner == 1 ? p1deck : p2deck); + + Util.Log($"Q22Part1: winner=p{winner}, score={score}"); + } + + static void Part2() + { + var p1deck = new List(list[1]); + var p2deck = new List(list[2]); + var winner = PlayGame(p1deck, p2deck, recursiveGame: true); + var score = GetScore(winner == 1 ? p1deck : p2deck); + + Util.Log($"Q22Part2: games played={gameNum}, deepest level={deepestLevel}, winner=p{winner}, score={score}"); } } }