using AdventOfCode.Core.Shared.IO; namespace AdventOfCode.Solutions._2023 { public class Day04 : IChallange { public int Year => 2023; public int Day => 4; private Dictionary _cardRuns = new Dictionary { { 1, 1 } }; private readonly IInputReader _inputReader; public Day04(IInputReader inputReader) { _inputReader = inputReader; _inputReader.SetInput(this); } public async Task GetSolutionPart1() { int total = 0; await foreach (string scratchCard in _inputReader.ReadAsStringLine()) { int power = GetWinningMatches(scratchCard) - 1; if (power >= 0) { total += (int)Math.Pow(2, power); } } return total.ToString(); } public async Task GetSolutionPart2() { int currentCard = 0; await foreach (string scratchCard in _inputReader.ReadAsStringLine()) { currentCard++; _ = GetRuns(currentCard); // ensure that there is always atleast one run for the count for (int i = 1; i <= GetWinningMatches(scratchCard); i++) { AddRunsToCard(currentCard + i, currentCard); } } return _cardRuns.Values.Sum().ToString(); } private int GetWinningMatches(string card) { string[] numbers = card.Split(':')[1].Split('|'); List winners = numbers[0].Split(' ') .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(int.Parse) .ToList(); return numbers[1].Split(' ') .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(int.Parse) .Where(winners.Contains) .Count(); } private void AddRunsToCard(int card, int currentCard) { if (!_cardRuns.ContainsKey(card)) _cardRuns.Add(card, 1); _cardRuns[card] += GetRuns(currentCard); } private int GetRuns(int card) { if (!_cardRuns.ContainsKey(card)) _cardRuns.Add(card, 1); return _cardRuns[card]; } } }