Skip to content

Advent of Code 2021 – Day 4

Christmas countdown

Photo by Any Lane from Pexels

I’m participating in the Advent of Code 2021. Here’s my solution for Day 4, Puzzle 1 – Giant Squid Bingo

Problem

Puzzle 1 for Day 4 is all about bingo. A giant squid has attached to the sub… for a game of bingo. In this case, we’ll process a set of 100 bingo cards and then “call” numbers one at a time until we get a bingo on one of the cards.

Solution

All my solutions are written in C#. You can find all my solutions in my Git repo.

We’ll start by setting up our list of bingo cards. Then, we’ll call each number one at a time. For each number called, we’ll iterate all of our bingo cards and mark matches with an “X”. After each mark we’ll check for a bingo. If we get a bingo, we’ll calculate our final score.

I ran into a problem with this that took me a while to figure out. I kept getting the wrong answer, until I eventually spotted that unlike normal bingo games, the solution they’re looking for doesn’t include diagonals. Once I edited out the diagonal code, I got the answer they were looking for.

Console.WriteLine("Advent of Code 2021");
Console.WriteLine("Day 4 - Puzzle 1");
//Solution logic goes here
string[] lines = System.IO.File.ReadAllLines("input.txt");
var bingoNumbers = lines[0].Split(',');
//build our boards list
var bingoboards = new List<string[,]>();
for (int i = 1; i < lines.Length; i++)
{
    if (string.IsNullOrEmpty(lines[i]))
    {
        //start new board
        string[,] board = new string[5, 5];
        for (int a = 1; a <= 5; a++)
        {
            //clean up some extra spaces and then parse rows into bingo boards
            var split = lines[i + a].Trim().Replace("  ", " ").Split(' ');
            for (int b = 0; b < 5; b++)
            {
                board[a - 1, b] = split[b];
            }
        }
        bingoboards.Add(board);
    }
}
//start calling numbers. For each number called, we will iterate all the boards and replace the called number with an X to indicate a marked number
for (int p = 0; p < bingoNumbers.Length; p++)
{
    var number = bingoNumbers[p];
    for(var q = 0; q < 100; q++)
    {
        var boardtomark = bingoboards[q];
        for (int y = 0; y < 5; y++)
        {
            for (int z = 0; z < 5; z++)
            {
                if (number.Equals(boardtomark[y, z]))
                {
                    boardtomark[y, z] = "X";
                    if (Bingo.CheckIfBoardIsBingo(boardtomark))
                    {
                        Bingo.CallBingo(boardtomark, number);
                    }
                }
            }
        }
    }
}
//Stop and wait for enter before exiting
Console.ReadLine();

public static class Bingo
{
    public static bool CheckIfBoardIsBingo(string[,] boardToCheck)
    {
        bool isBingo = false;
        //horizontals
        for (int a = 0; a < 5; a++)
        {
            isBingo = true;
            for (int b = 0; b < 5; b++)
            {
                if (boardToCheck[a, b] != "X")
                {
                    isBingo = false;
                    break;
                }
            }
            if (isBingo) return true;
        }
        //verticals
        for (int x = 0; x < 5; x++)
        {
            isBingo = true;
            for (int y = 0; y < 5; y++)
            {
                if (boardToCheck[y, x] != "X")
                {
                    isBingo = false;
                    break;
                }
            }
            if (isBingo) return true;
        }
        //diagonals
        //if (boardToCheck[2, 2] != "X") return false;
        //for (int c = 0; c < 5; c++)
        //{
        //    isBingo = true;
        //    if (boardToCheck[c, c] != "X")
        //    {
        //        isBingo = false;
        //        break;
        //    }
        //}
        //if (isBingo) return true;
        //for (int d = 4; d >= 0; d--)
        //{
        //    isBingo = true;
        //    if (boardToCheck[d, d] != "X") return false;
        //}
        return isBingo;
    }
    public static void CallBingo(string[,] bingoBoard, string numberCalled)
    {
        Console.WriteLine("BINGO!!!!");
        int unmatchedTotal = 0;
        for (int f = 0; f < 5; f++)
        {
            for (int g = 0; g < 5; g++)
            {
                Console.Write($"{bingoBoard[f, g].PadLeft(3)}");
                if (bingoBoard[f, g] != "X")
                {
                    unmatchedTotal += Convert.ToInt32(bingoBoard[f, g]);
                }
            }
            Console.WriteLine();
        }
        Console.WriteLine();
        Console.WriteLine($"Last Number Called: {numberCalled}");
        Console.WriteLine($"Sum of unmatched: {unmatchedTotal * Convert.ToInt32(numberCalled)}");
        Console.WriteLine();
        Console.WriteLine();
        //return;
        Console.ReadLine();
        Environment.Exit(0);
    }
}

The answer is 89001

Problem 2

Puzzle 2 for Day 4 continues the bingo game. This time we’ll let the squid win. So, instead of finding the first winning care, we’re going to find the last winning card.

Solution

All my solutions are written in C#. You can find all my solutions in my Git repo.

Only a couple of small changes to our puzzle 1 code is needed. First, after we find bingo matches, we need to remove those cards from the pool of options. That way we can make sure we’re not continuing to search cards after it scores a win. Next, instead of stopping after the first match, we keep looking until we find all the matches that can occur. Then, we’ll report the last win in the list.

Console.WriteLine("Advent of Code 2021");
Console.WriteLine("Day 4 - Puzzle 1");
//Solution logic goes here
string[] lines = System.IO.File.ReadAllLines("input.txt");
var bingoNumbers = lines[0].Split(',');
//build our boards list
var bingoboards = new List<string[,]>();
for (int i = 1; i < lines.Length; i++)
{
    if (string.IsNullOrEmpty(lines[i]))
    {
        //start new board
        string[,] board = new string[5, 5];
        for (int a = 1; a <= 5; a++)
        {
            //clean up some extra spaces and then parse rows into bingo boards
            var split = lines[i + a].Trim().Replace("  ", " ").Split(' ');
            for (int b = 0; b < 5; b++)
            {
                board[a - 1, b] = split[b];
            }
        }
        bingoboards.Add(board);
    }
}
//start calling numbers. For each number called, we will iterate all the boards and replace the called number with an X to indicate a marked number
for (int p = 0; p < bingoNumbers.Length; p++)
{
    var number = bingoNumbers[p];
    var boardCount = bingoboards.Count;
    var  boardsToRemove = new List<string[,]>();
    for(var q = 0; q < boardCount; q++)
    {
        var boardtomark = bingoboards[q];
        for (int y = 0; y < 5; y++)
        {
            for (int z = 0; z < 5; z++)
            {
                if (number.Equals(boardtomark[y, z]))
                {
                    boardtomark[y, z] = "X";
                    if (Bingo.CheckIfBoardIsBingo(boardtomark))
                    {
                        Bingo.CallBingo(boardtomark, number);
                        boardsToRemove.Add(boardtomark);
                    }
                }
            }
        }
    }
    
    //remove any boards that already scored a bingo
    foreach (var item in boardsToRemove)
    {
        bingoboards.Remove(item);
    }
}
//Stop and wait for enter before exiting
Console.ReadLine();

public static class Bingo
{
    public static bool CheckIfBoardIsBingo(string[,] boardToCheck)
    {
        bool isBingo = false;
        //horizontals
        for (int a = 0; a < 5; a++)
        {
            isBingo = true;
            for (int b = 0; b < 5; b++)
            {
                if (boardToCheck[a, b] != "X")
                {
                    isBingo = false;
                    break;
                }
            }
            if (isBingo) return true;
        }
        //verticals
        for (int x = 0; x < 5; x++)
        {
            isBingo = true;
            for (int y = 0; y < 5; y++)
            {
                if (boardToCheck[y, x] != "X")
                {
                    isBingo = false;
                    break;
                }
            }
            if (isBingo) return true;
        }
        return isBingo;
    }
    public static void CallBingo(string[,] bingoBoard, string numberCalled)
    {
        Console.WriteLine("BINGO!!!!");
        int unmatchedTotal = 0;
        for (int f = 0; f < 5; f++)
        {
            for (int g = 0; g < 5; g++)
            {
                Console.Write($"{bingoBoard[f, g].PadLeft(3)}");
                if (bingoBoard[f, g] != "X")
                {
                    unmatchedTotal += Convert.ToInt32(bingoBoard[f, g]);
                }
            }
            Console.WriteLine();
        }
        Console.WriteLine();
        Console.WriteLine($"Last Number Called: {numberCalled}");
        Console.WriteLine($"Sum of unmatched: {unmatchedTotal * Convert.ToInt32(numberCalled)}");
        Console.WriteLine();
        Console.WriteLine();
        return;
    }
}

The answer is 7296