Skip to content

Advent of Code interfaces to improve your life

Posted in Advent of Code

Why this post?

Hello there, JD here, I have been writing quite a bit about the Advent of Code. And since we’re half-way through Day 3, I figured I could try to help out my fellow coders. Help by offering you some structure that can help you focus on your daily challenge rather than setup. In order to do that, you can have the main structure of your code rely on some interfaces. Some Advent of Code interfaces.

As you may know, I’m participating in my third consecutive Advent of code this year. Last year I realized early on that it is safe to assume that the input will always be an array of strings and the output can be considered a string.

Advent of Code interfaces and snippets a.k.a the reason you clicked

That allows for some reusability in terms of writing our code. That’ll allow you to have that sort of interface in Go:

package days

// A Day that can compute a result from an input
type Day interface {
    Part1(Input) (Result, error)
    Part2(Input) (Result, error)
}

// An Input is used to compute a Result for a Day
type Input []string

// The Result of a Day's computation
type Result string

Now this would give us in C# that look something like :

namespace AdventOfCode
{
    public interface Day
    {
        string Part1(string[] input);
        string Part2(string[] input);
    }
}

These Advent of Code interfaces will allow you to have your main class/piece of code to use the interface with code that barely changes while your day-based classes will be all about the problem-solving logic. As the Go example below shows:

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/codingnagger/advent-of-code-2020/pkg/days"
	"github.com/codingnagger/advent-of-code-2020/pkg/days/day3"
)

func main() {
	start := time.Now()

	today := &day3.Computer{}

	input := readInput("./assets/input/day3.txt")

	res, err := today.Part2(input)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("\n%s\n", res)

	elapsed := time.Since(start)
	fmt.Printf("\nExecution took %s\n", elapsed)
}

func readInput(filename string) days.Input {
	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	res := []string{}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		res = append(res, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}

	return res
}

Now C#:

namespace AdventOfCode
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            TwoPartDay day = new Day18();
            // var input = File.ReadAllLines("./input/day18.txt");
            
            Console.WriteLine(day.Part1(input));  
            // Console.WriteLine(day.Part2(input));  

            stopWatch.Stop();

            DisplayDuration(stopWatch);
        }

        static void DisplayDuration(Stopwatch stopWatch) {
            Console.WriteLine("RunTime " + DisplayUtils.DisplayValue(stopWatch));
        }
    }
}

Farewell and may the Advent be with you

I pulled and adjusted the snippets from my participation in C# last year and Golang this year. I hope that this post will help you focus on your problem of the day and save some time. Don’t hesitate to let me know if you gained an advantage with these Advent of Code interfaces. Hopefully, they will help you improve your ranking if that’s what you’re after.

Thank you for reading this post and if you want to read more of my Advent of Code entries, you can have a look right here. However, if you’re interested in deploying a container to AWS using Fargate tasks, click there.

Happy Advent of Code and good luck!

Be First to Comment

    Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.

    %d bloggers like this: