wolfgang ziegler


„make stuff and blog about it“

A C# Grid Helper Class for the Advent of Code puzzles

October 30, 2021

Advent of Code

Most people I talk to are familiar with the Advent of Code puzzles for quite a while already. I however had been living under a rock apparently and only discovered this great project last December but was immediately addicted.

One of my goals for this year was to finish all old puzzles back to 2015 before the new ones arrive this December. At the time of writing this article, I have 281 out of 300 possible stars, so I still have a fighting chance of achieving this goal.

My advent of code stats - 281/300 stars

A Grid helper

The reason I am writing this blog post and wrote my Grid helper class, is that many of the Advent Of Code (AoC) puzzles involve parsing and manipulating grids of text to do Game of Life-like simulations or explore mazes.

One of the AoC sample grids

After having written the same code for parsing and printing grids and counting the neighbors of grid cells over and over again, I decided to write this little helper class explicitly for grids.

Using the Grid helper

Here are a few examples of how to use this helper class.

Assuming we have a file input.txt that specifies the grid we are working with (consisting of . and # cells).

##.#.
#..#.
.....
....#
#.###

The grid can be parsed and printed (width, height, textual representation) like this:

var grid = Grid.FromFile("input.txt");
Console.WriteLine($"Width: {grid.Width}, Height: {grid.Height}");
Console.WriteLine();
// Print to console
grid.Print();
Console.WriteLine();
// Print to StringBuilder
var sb = new StringBuilder();
grid.PrintTo(sb);
Console.WriteLine(sb);

Output:

Width: 5, Height: 5

##.#.
#..#.
.....
....#
#.###

##.#.
#..#.
.....
....#
#.###

##.#.
#..#.
.....
....#
#.###

Grids can easily be cloned:

var grid2 = grid.Clone();
grid2.Print();

Output (as expected equal to the original):

##.#.
#..#.
.....
....#
#.###

Another useful and often-needed feature is counting different grid cells, individually (e.g. only #) or all distinct ones.

// CountDistinct
foreach (var c in grid.CountDistinct())
{
	Console.WriteLine($"'{c.Key}': {c.Value}");
}
Console.WriteLine();
// Count
Console.WriteLine($"count '#': {grid.Count('#')}");
Console.WriteLine($"count 'x': {grid.Count('x')}");

Output:

'#': 10
'.': 15

count '#': 10
count 'x': 0

Filling all cells of the grid with a specified character and setting individual ones is also quite useful.

// Fill
grid2.Fill('x');
grid2.Print();
Console.WriteLine();
// Indexing
grid2[0, 0] = '*';
grid2[0, 4] = '+';
grid2.Print();

Output:

xxxxx
xxxxx
xxxxx
xxxxx
xxxxx

*xxxx
xxxxx
xxxxx
xxxxx
+xxxx

Another typical use case is counting the content of adjacent cells (e.g. for Game of Life simulations). Grid provides a range of methods for that.

// CountAdjacent4Distinct
foreach (var c in grid.CountAdjacent4Distinct(1, 1))
{
  Console.WriteLine($"'{c.Key}': {c.Value}");
}
Console.WriteLine();
// CountAdjacent8Distinct
foreach (var c in grid.CountAdjacent8Distinct(1, 1))
{
  Console.WriteLine($"'{c.Key}': {c.Value}");
}
Console.WriteLine();
// CountAdjacent4
Console.WriteLine($"{grid.CountAdjacent4(1, 1, '#')}");
Console.WriteLine();
// CountAdjacent8
Console.WriteLine($"{grid.CountAdjacent8(1, 1, '#')}");
Console.WriteLine();
// IsInBounds
Console.WriteLine($"1/1 in bounds: {grid.IsInBounds(1, 1)}");
Console.WriteLine($"1/10 in bounds: {grid.IsInBounds(1, 10)}");

Output:

'#': 2
'.': 2

'#': 3
'.': 5

2

3

1/1 in bounds: True
1/10 in bounds: False

That's all, folks

Frankly, that's all there is for now. I will start using it in the puzzles to come and plan to keep adding functionality where it makes sense. If you like it and think it's a good idea, head over to GitHub, use the code and contribute.

Until then, I'm looking forward to the Advent of Code 2021!