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.