2021 Advent of code: Day 4, part 1

2D arrays in C#

I decided to make time to go through AdventOfCode 2021.

I have reached day 4 part 1 and figured I would share how I approached the problem.

I decided to take the bingo card matrix and store it in a 2D array. I then created another 2D matrix to mark when that position is covered.

I stored these two in a Dictionary with a sequential key and appended "a" for the position being covered and "s" for the source numbers.

After that is just a matter of looping.

I am just showing the function does the work.

The OnDebugMessage is a C# EventHandler that is defined as such:

        public event EventHandler<AdventofCode2021Args> DebugMessageEvent;

        protected virtual void OnDebugMessage(string DebugMessage)
        {
            DebugMessageEvent?.Invoke(this, new AdventofCode2021Args() { DebugMessage = DebugMessage });
        }

The EventHandler saves me from having to specify the delegate code.

public int Day4Part1(IReadOnlyList<int> bingoNumbers, List<int[,]> bingoCards, bool FindLast)
        {
            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 numbersUsed = 0;

            foreach (int num in bingoNumbers)
            {
                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;
                            }
                        }
                    }
                }

                numbersUsed++;

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

                //Check answers
                bool IsAnswerFound = false;
                int totalUnmarked = 0;

                if (FindLast)
                {

                }
                else
                {
                    foreach (KeyValuePair<string, int[,]> answerValuePair in CardsAndTracking.Where(c => c.Key.EndsWith("a")))
                    {
                        //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)
                            {
                                IsAnswerFound = true;
                            }

                            if (IsAnswerFound) { break; }
                        }

                        if (!IsAnswerFound)
                        {
                            //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)
                                {
                                    IsAnswerFound = true;
                                }

                                if (IsAnswerFound) { break; }
                            }
                        }

                        if (IsAnswerFound)
                        {
                            //Tally up on the cardValuePair.Value matrix
                            for (int i = 0; i < answerValuePair.Value.GetLength(0); i++)
                            {
                                for (int j = 0; j < answerValuePair.Value.GetLength(1); j++)
                                {
                                    if (answerValuePair.Value[i, j] == 0)
                                    {
                                        string key = answerValuePair.Key.Substring(0, answerValuePair.Key.Length - 1);
                                        totalUnmarked += CardsAndTracking[key + "s"][i, j];
                                    }
                                }
                            }

                            break;
                        }
                    }
                }

                if (IsAnswerFound)
                {
                    finalscore = totalUnmarked * num;
                    break;
                }

            }

            return finalscore;
        }

The FindLast boolean is where I just started working through part 2. Will see how much I refactor the current code.

It is interesting to see after I get the answer correct how others have solved it. I found one person's solution that used classes to hold the bingo rows and numbers. Seeing the data in a matrix format biased me to using 2D arrays.