Advent of Code 2021: Day 4, Part 2

Photo by Trent Erwin on Unsplash

Advent of Code 2021: Day 4, Part 2

Have a plan and use encapsulation

Lessons reinforced:

  • Encapsulation makes modifications cleaner
  • Writing out your logic (and referring to it while coding) is a good thing

Writing code, like any endeavor that creates things, has tradeoffs. You don't know what to tradeoffs to make if you don't know the goal of the effort.

I am doing these challenges to exercise my thinking with problems I am rarely asked to tackle during my 9-5 job. I also like to compare how I approached the problem compared to other. This allows me to see my thinking in a different light. I get to learn tidbits of coding I might not have otherwise.

The code I am doing for these challenges is not meant to be reusable nor easily maintainable. The goal is to get the "star", the answer. The secondary goal is to grow more familiar with the C# language and challenge the habits I have accrued over the years.

public int Day4Part1_2(IReadOnlyList<int> bingoNumbers, List<int[,]> bingoCards, bool FindLast)
        {
            /*Part 2
             * When bingo card filled, remove it from further processing
             */
            OnDebugMessage(string.Format("Looking for {0} answer", FindLast ? "Last" : "First"));

            int finalscore = 0;
            Dictionary<string, int[,]> CardsAndTracking = new Dictionary<string, int[,]>();

            int bingoCardID = 0;
            foreach(int[,] b in bingoCards)
            {
                int[,] tmp = new int[b.GetLength(0), b.GetLength(1)];
                CardsAndTracking.Add(bingoCardID.ToString() + "s", b);
                CardsAndTracking.Add(bingoCardID.ToString() + "a", tmp);
                bingoCardID++;
            }

            int LastNumberMatched = 0;
            KeyValuePair<string, int[,]> bingoCardFound = new KeyValuePair<string, int[,]>();
            KeyValuePair<string, int[,]> bingoCardFoundAnswers = new KeyValuePair<string, int[,]>();
            int numbersUsed = 0;

            foreach (int num in bingoNumbers)
            {
                numbersUsed++;

                if (CardsAndTracking.Count == 0)
                {
                    OnDebugMessage("No more cards to play bingo");
                    break;
                }

                foreach(KeyValuePair<string, int[,]> cardValuePair in CardsAndTracking.Where(c => c.Key.EndsWith("s")))
                {
                    for (int i = 0; i < cardValuePair.Value.GetLength(0); i++)
                    {
                        for (int j = 0; j < cardValuePair.Value.GetLength(1); j++)
                        {
                            if (num == cardValuePair.Value[i,j])
                            {
                                string key = cardValuePair.Key.Substring(0, cardValuePair.Key.Length - 1);
                                CardsAndTracking[key + "a"][i, j] = 1;
                            }
                        }
                    }
                }

                //Data in test is matrix at 5
                if (numbersUsed < 5) { continue; }
                OnDebugMessage("Starting to check for bingo...number:" + num);

                //Check answers
                List<string> keysToRemove = new List<string>();

                foreach (KeyValuePair<string, int[,]> answerValuePair in CardsAndTracking.Where(c => c.Key.EndsWith("a")))
                {
                    bool ThisCardIsBingo = false;

                    //Check rows for 5 match
                    for (int i = 0; i < answerValuePair.Value.GetLength(0); i++)
                    {
                        int rowTotal = 0;
                        for (int j = 0; j < answerValuePair.Value.GetLength(1); j++)
                        {
                            rowTotal += answerValuePair.Value[i, j];
                        }

                        if (rowTotal == 5)
                        {
                            bingoCardFoundAnswers = answerValuePair;
                            string key = answerValuePair.Key.Substring(0, answerValuePair.Key.Length - 1);
                            bingoCardFound = CardsAndTracking.Where(c => c.Key == key + "s").SingleOrDefault();
                            LastNumberMatched = num;
                            ThisCardIsBingo = true;
                            keysToRemove.Add(bingoCardFound.Key);
                            keysToRemove.Add(bingoCardFound.Key.Substring(0, bingoCardFound.Key.Length - 1) + "a");
                            break;
                        }
                    }

                    if (!ThisCardIsBingo)
                    {
                        //Check columns for 5 match
                        for (int j = 0; j < answerValuePair.Value.GetLength(1); j++)
                        {
                            int columnTotal = 0;
                            for (int i = 0; i < answerValuePair.Value.GetLength(0); i++)
                            {
                                columnTotal += answerValuePair.Value[i, j];
                            }

                            if (columnTotal == 5)
                            {
                                bingoCardFoundAnswers = answerValuePair;
                                string key = answerValuePair.Key.Substring(0, answerValuePair.Key.Length - 1);
                                bingoCardFound = CardsAndTracking.Where(c => c.Key == key + "s").SingleOrDefault();
                                LastNumberMatched = num;
                                ThisCardIsBingo = true;
                                keysToRemove.Add(bingoCardFound.Key);
                                keysToRemove.Add(bingoCardFound.Key.Substring(0, bingoCardFound.Key.Length - 1) + "a");
                                break;
                            }
                        }
                    }

                    if (!FindLast
                        && ThisCardIsBingo)
                    {
                        break;
                    }
                }//loop for answer cards

                if (FindLast)
                {
                    foreach (string keyBeGone in keysToRemove)
                    {
                        CardsAndTracking.Remove(keyBeGone);
                    }
                }

                if (!FindLast
                    && bingoCardFound.Key != null)
                {
                    break;
                }

            }//loop for numbers

            if (bingoCardFound.Key != null)
            {
                int totalUnmarked = 0;
                for (int i = 0; i < bingoCardFoundAnswers.Value.GetLength(0); i++)
                {
                    for (int j = 0; j < bingoCardFoundAnswers.Value.GetLength(1); j++)
                    {
                        if (bingoCardFoundAnswers.Value[i, j] == 0)
                        {
                            totalUnmarked += bingoCardFound.Value[i, j];
                        }
                    }
                }

                finalscore = LastNumberMatched * totalUnmarked;
            }

            return finalscore;
        }