Tidy.AdventOfCode 2.0.3

.NET 7.0
dotnet add package Tidy.AdventOfCode --version 2.0.3
NuGet\Install-Package Tidy.AdventOfCode -Version 2.0.3
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Tidy.AdventOfCode" Version="2.0.3" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Tidy.AdventOfCode --version 2.0.3
#r "nuget: Tidy.AdventOfCode, 2.0.3"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install Tidy.AdventOfCode as a Cake Addin
#addin nuget:?package=Tidy.AdventOfCode&version=2.0.3

// Install Tidy.AdventOfCode as a Cake Tool
#tool nuget:?package=Tidy.AdventOfCode&version=2.0.3

Advent of Code logo

Tidy.AdventOfCode

Yo, ho ho!

Tidy.AdventOfCode is a free, simple runner and framework for creating and posting your solutions for the awesome <a href="https://adventofcode.com/" target="_blank">Advent of Code</a> yearly riddle-fest in (the also awesome) .NET!

What it does

Tidy.AdventOfCode provides a framework for running your solutions for Advent of Code riddles, and that means there are predefined types (like Day<T>) that help you organize your code or reduce boilerplate. If you follow the example below, you'll see everything will "just work". You add your solution for the day, start the runner (providing the proper year, dayNumber and part values are still your responsibility, maybe use a Console.ReadLine() for getting them from the console), and your solution gets automagically calculated for the input that gets pulled (and cached ) from the server. Then, your answer in hand, your solution gets posted to the server, and the result from the server gets rendered on your console!

What's new?

The list of changes can be found at the release notes.

Prerequisites

You need at least <a href="https://dotnet.microsoft.com/download/dotnet/" target="_blank">version 5.0 of the .NET SDK</a> installed. Nothing else. Although a <a href="https://code.visualstudio.com/" target="_blank">code editor</a> or an <a href="https://visualstudio.microsoft.com/" target="_blank">IDE</a> might be a good idea.

Low maintenance

  1. Create a new Console app:

    > dotnet new console -f net5.0

  2. Add a little Tidy.AdventOfCode NuGet sprinkle:

    > dotnet add package Tidy.AdventOfCode

  3. Create a default runner (replace Program.cs):

    await Tidy.AdventOfCode.Runner.CreateDefault().ExecuteAsync(); // Yes, one line!
    
  4. Log in to the <a href="https://adventofcode.com/" target="_blank">Advent of Code</a> site and copy the value of the session cookie:

    Copy your the value from the cookie named 'session'

  5. Save the value in a file at the above directory named cookie.txt:

    Save the value of your 'session' cookie in a file named  'cookie.txt'

  6. Create your solution for the day:

    using System.Linq;
    using Tidy.AdventOfCode;
    
    namespace YourName.AdventOfCode.Year2020
    {
        class Day1 : Day
        {
            public override object ExecutePart1() => Input.Count(c => c is '(' or ')');
        }
    }
    
    
  7. Watch, as magic happens!

    > dotnet run

Things to note

The biggest issue you might run into is when you submit answers less, than a minute apart each other. In this case, for your consequent calls, the warning message will be cached for your answer (whether it was the right or wrong one). In this case you might need to manually delete the corresponding cache entries (or the cache entirely, if you like). Not an issue since version 1.2.1.

The public API is fully documented (it is of good quality too, if I may say so myself), so you can start hacking away as much as you like and find new things to do magic with.

The API is designed in a way to be fully expandable (by inheriting) or to be as easy as possible.

For pros, you can switch out any of the underlying services that are registered in the service provider. IDay instances are instantiated using DI.

The Advent of Code server isn't designed to be used this way. Please, be mindful and don't use any of your code for malicious purposes, such as DDOSing the server. You are identified by your IP address (and specifically, by the session cookie), so consider yourself informed.

If you have some questions, feel free to browse the source or open an issue. I don't plan to extend the current solution very much (unless public demand shows to or I happen to get another), so if you wish to modify anything in the framework, feel free to open a pull request or fork the repo.

The cached inputs, answers and responses are all in a human-readable and machine-readable format, so feel free to abuse the cache folder to your liking.

Pro tips

There are some <a href="https://tyrrrz.me/blog/fluent-generics">fluent generics</a> used to construct differently parsed input-handling Day<T> objects, such as Day<T>.WithParser<TParser>. Yes, that is a type! This can reduce boilerplate parsing the input values quite significantly. More info can be found describing version 2.0.0 of the release notes.

You can create your own Runner, if you would only like a part of the functionality Tidy.AdventOfCode provides. There is also a handy extension method for registering with any IServiceCollection, like services.AddTidyAdventOfCode(...).


Keep on hackin'! Click the ⭐!

Tidy.AdventOfCode - Release Notes

2.0.3

Added a user-agent string to outgoing HTTP requests in the format: .NET/7.0.0 Tidy.AdventOfCode/2.0.3 (+https://github.com/yugabe/Tidy.AdventOfCode), as it was requested by Eric on Reddit.

2.0.2

Another minor fix: when returning with a long value from your solution, there was a chance for the long-string-int safe conversion to fail when trying to create the file in the file system. Now the conversion uses long values.

2.0.1

Well, the first bug has shown its head. Introduced with the feature in 1.2.1, the correct string to look for in the response didn't have the correct punctuation (there is no pediod character after the text "You gave an answer too recently"). I always say: Don't use magic strings in your code!... but it seems even I can't follow my own advice. Oh well.

I have to say, it's a little bit of a Christmas miracle it took this long for a bug to show up at all 🐱‍👤

Migration from 1.2.1~2.0.0 to 2.0.1 or above

If you jumped the gun on 1.2.1 or 2.0.0 early, you have to clear the wrong responses from your cache directory manually.

2.0.0

The first breaking change! It's nothing major though. Created a simple Day class to inherit from when using no parsing of the input value (instead of using Day<TAnything>.Raw, which actually was still a Day<string> and TAnything was discarded). So now you can inherit from these classes you can write your solutions in:

  • Day: Inherit from this class when you don't want to parse the input to any other format. This way you have access to the raw input (as a string value accessible via the Input property). Technically this is a subclass of Day<string>.
  • Day.NewLineSplitParsed<T>: Inherit from this class when you don't want to parse the input, but want to convert it to a simple T type like int or float for each line of the input. The conversion is automatic by using the default TypeConverter for the given T type, but it might fail (in which case you have to choose any of the other ones). Technically this is a subclass of Day<T[]>.
  • Day<T>: Inherit from this class when you want to work on an input of type T. You have to provide the parsing by overriding the ParseInput method.
  • Day<T>.WithParser<TParser>: Inherit from this class when you want to work on an input of type T, and you want to use an IParser<T> object that can parse simple text to a T instance.

Also, ISimpleParser and IMultipleParser were consolidated into IParser, and you are given the option to... well... simply parse into whatever data structure you like. The corresponding APIs broke as a result, so you'll have to rename your ForMany and ForOne calls to WithParser, and rename the implementor's ParseOne and ParseMany methods to... yeah, you guessed it: Parse.

Migration from 1.. to 2.0.0

Your solutions which inherited from Day<_>.Raw now should inherit from Day. Your solutions which inherited from Day<_>.NewLineSplitParsed<T> should now inherit from Day.NewLineSplitParsed<T>.

No other changes are necessary.

1.2.1

Now the server responses won't be cached if the response's parsed content contains the text "You gave an answer too recently.".

1.2.0

So much work, so little code! Now you can run the runner with all the default settings by just putting this into your Program.cs file:

await Tidy.AdventOfCode.Runner.CreateDefault().ExecuteAsync();

I mean, yeah, that's ALL the code that's needed, not even any more usings or anything.

The little features that made these possible are:

  • A new IParameterParser service, that can parse strings to year-dayNumber(-part) tuples.
  • A new caching mechanism, that stores the last parameters that are supplied to the runner's ExecuteAsync method.
  • The default cache directory on Windows is the APPDATA (usually C:\Users\you\AppData\Roaming) folder's 'Tidy.AdventOfCode' subdirectory. You can find all the cached files here.

1.1.0

Made the Runner configurable in a few aspects:

  • Configuration is done optionally using the provided action in IServiceCollection.AddTidyAdventOfCode or Runner.CreateDefault.
  • You can disable automatically getting your inputs from the server. In this case, you have to put your input files according to the IApiCacheManager instance's internal policy (which is, by default placed in the provided directory root's Inputs folder named YYYY-D.txt or YYYY-DD.txt). If no file would be found, you'll get an exception.
  • You can disable automatically posting your results to the server. You'll still get the results in the console output.
  • You can choose to automatically copy the results of the last successful run to the clipboard using cmd, echo and clip (on Windows only, on other platforms this flag is ignored).

Keep on hackin'! Click the ⭐!

Product Versions
.NET net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.3 45 12/1/2022
2.0.2 301 12/10/2020
2.0.1 339 12/6/2020
2.0.0 275 12/4/2020
1.2.1 252 12/4/2020
1.2.0 276 12/3/2020
1.1.0 281 12/3/2020
1.0.0 265 12/2/2020