DEV Community

Cover image for A small .NET template to back you up
Pierre Bouillon
Pierre Bouillon

Posted on • Updated on

A small .NET template to back you up

As usual, for December, the Advent of Code challenge has once again started this year.

I've been trying to do doing it for quite some time now, always in C#, and always have had to type the same code:

  1. The parser for the input file
  2. The solution for the first puzzle
  3. The test for the example
  4. The test for the solution
  5. The solution for the second puzzle
  6. The test for the example
  7. The test for the solution

It may not be much, but it results in either an inconsistent way of solving the puzzles or in a lot of redundancy in the code for each day.

To spare some time (or at least spare some of yours), I created a small GitHub template repository so that you can quickly get started on the implementation on this year's puzzles and not on the boilerplate to do so:

GitHub logo pBouillon / dotnet-advent-of-code-template

Advent of Code template for .NET contenders, focus on the puzzle, let it handle the rest

Dotnet Advent of Code

Advent of Code template for .NET contenders, focus on the puzzle, let it handle the rest

After gaining yours, consider leaving a small to this project too!


Advantages

In order to solve your puzzle, you might need the debugger from time to time, especially as the puzzles become harder.

This template is built around test projects, in order to take advatage of the debugging possibilities and TDD if you want to.

Here are also a bunch of features offered by the template:

  • Retrieval of the puzzle input localy or remotely
  • Testing of the puzzle examples
  • Conditionnaly skip the tests of a puzzle if wanted

Usage

This template exposes two classes: a Solver and a TestEngine The .NET CI is also preconfigured to ensure that all your tests are valid.

To get started with a new year, just create a new xUnit project and add…

It also comes with the GitHub Action's CI preconfigured and a demo project if you need some guidance.

Usage

It's usage is fairly simple:

  • For your logic, inherit from Solver
  • To test your logic against the example and find your solution, inherit from TestEngine

The Solver

The solver is the place where you can specify where your input is, how and to what you want it to be parsed, and the logic to solve the first and second part of the puzzle.

Let's see its usage with an example:

If the first part of the puzzle is "Given a list of integers, find the greatest one" and the second one "Now find the sum of them", we can do the following:

public class Solver : Solver<int[], int>
{
    protected override string InputPath => "input.txt";

    public override int PartOne(int[] input)
        => input.Max();

    public override int PartTwo(int[] input)
        => input.Sum();

    public override int[] ReadInput(string inputPath)
        => File
            .ReadAllLines(inputPath)
            .Select(int.Parse)
            .ToArray();
}
Enter fullscreen mode Exit fullscreen mode

The TestEngine

The test engine is the class that will allow you to check if your solutions are right.

For each part, you will be asked to specify what your example is and what solution you are expecting.

Of course, the solution is unknown at first and making this test fail will show you your solution.

For our example, we may have written the following:

public class SolverTest : TestEngine<Solver, int[], int>
{
    public override Puzzle PartOne => new()
    {
        Example = new()
        {
            Input = new[] { 1, 2, 3 },
            Result = 3,
        },

        Solution = 5,
    };

    public override Puzzle PartTwo => new()
    {
        Example = new()
        {
            Input = new[] { 1, 2, 3 },
            Result = 6,
        },

        Solution = 15,
    };
}
Enter fullscreen mode Exit fullscreen mode

That's pretty much all about it, I hope that it will help others to get through this year's puzzle, and see you on the 24th! 🎄


Photo by Michel Stockman on Unsplash

Top comments (0)