Add benchmark support using -b

This commit is contained in:
2022-12-17 21:48:16 +01:00
parent 147c348ee1
commit 63c866f5a0
20 changed files with 469 additions and 341 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ riderModule.iml
/_ReSharper.Caches/
.idea/.idea.AdventOfCode/.idea
AdventOfCode.sln.DotSettings.user
BenchmarkDotNet.Artifacts

View File

@@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="Spectre.Console" Version="0.45.0" />
</ItemGroup>

23
DayBenchmarker.cs Normal file
View File

@@ -0,0 +1,23 @@
using AdventOfCode.Days;
using BenchmarkDotNet.Attributes;
namespace AdventOfCode;
[ShortRunJob]
[MemoryDiagnoser(false)]
public class DayBenchmark
{
private Day Day => new Day15();
[Benchmark]
public void Part1()
{
Day.RunPart1(display: false);
}
[Benchmark]
public void Part2()
{
Day.RunPart2(display: false);
}
}

View File

@@ -4,9 +4,9 @@ public abstract class Day
{
public abstract int Number { get; }
public abstract string Name { get; }
public abstract void RunPart1();
public abstract void RunPart2();
public abstract void RunPart1(bool display = true);
public abstract void RunPart2(bool display = true);
public override string ToString()
{

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ public class Day10 : Day
{
public override int Number => 10;
public override string Name => "Cathode-Ray Tube";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
int cycle = 1;
int x = 1;
@@ -47,10 +47,13 @@ public class Day10 : Day
}
}
AnsiConsole.MarkupLine($"[green]Sum of signal strengths: [yellow]{sum}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Sum of signal strengths: [yellow]{sum}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
// Setup the CRT
const char litPixel = '#';
@@ -122,7 +125,10 @@ public class Day10 : Day
}
// Print the CRT
AnsiConsole.Write(crtCanvas);
if (display)
{
AnsiConsole.Write(crtCanvas);
}
}
#region Input

View File

@@ -51,9 +51,9 @@ public class Monkey
// Divide worry level by 3 before test
if (divideWorry)
{
newValue = newValue / 3;
newValue = newValue / 3;
}
// Even using this simplification, it's still needed to use longs because
// they sometime overflow before being simplified in part 2
newValue = newValue % (2*3*5*7*11*13*17*19);
@@ -77,7 +77,7 @@ public class Day11 : Day
{
public override int Number => 11;
public override string Name => "Monkey in the Middle";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
const int roundsCount = 20;
@@ -95,10 +95,13 @@ public class Day11 : Day
var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList();
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
const int roundsCount = 10_000;
@@ -116,7 +119,10 @@ public class Day11 : Day
var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList();
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
}
}
private static IImmutableList<Monkey> ParseMonkeys()

View File

@@ -43,7 +43,7 @@ public class Day12 : Day
private (int x, int y) _end;
private (int x, int y) _start;
public override void RunPart1()
public override void RunPart1(bool display = true)
{
var map = ParseMap();
var canvas = DrawMap(map);
@@ -57,13 +57,16 @@ public class Day12 : Day
canvas.SetPixel(x, y, Color.White);
}
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
var map = ParseMap();
var canvas = DrawMap(map);
@@ -77,10 +80,13 @@ public class Day12 : Day
canvas.SetPixel(x, y, Color.White);
}
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
}
}
private (int length, List<(int x, int y)> path) ExplorePath(byte[,] map)

View File

@@ -153,7 +153,7 @@ public class Day13 : Day
{
public override int Number => 13;
public override string Name => "Distress Signal";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
var pairs = ParsePacketPairs();
@@ -169,10 +169,13 @@ public class Day13 : Day
}
}
AnsiConsole.MarkupLine($"[green]Right order pair indices sum: [yellow]{sum}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Right order pair indices sum: [yellow]{sum}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
var packets = ParsePackets();
@@ -186,7 +189,11 @@ public class Day13 : Day
var firstDividerIndex = orderedPackets.IndexOf(firstDivider) + 1;
var lastDividerIndex = orderedPackets.IndexOf(lastDivider) + 1;
AnsiConsole.MarkupLine($"[green]Decoder key is: [yellow]{firstDividerIndex * lastDividerIndex}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Decoder key is: [yellow]{firstDividerIndex * lastDividerIndex}[/][/]");
}
}
private static PacketElement ReadElement(ref ReadOnlySpan<char> packet)
{

View File

@@ -121,7 +121,7 @@ public class Day14 : Day
private readonly Point _sandSource = new(500, 0);
private Point _offsetSandSource;
public override void RunPart1()
public override void RunPart1(bool display = true)
{
var map = GenerateMap();
@@ -136,12 +136,15 @@ public class Day14 : Day
sandBlocksCount++;
}
AnsiConsole.Write(canvas);
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.MarkupLine($"[green]Total sand blocks: [yellow]{sandBlocksCount}[/][/]");
AnsiConsole.MarkupLine($"[green]Total sand blocks: [yellow]{sandBlocksCount}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
var map = GenerateDictionaryMap();
@@ -156,9 +159,13 @@ public class Day14 : Day
sandBlocksCount++;
}
AnsiConsole.Write(GenerateCanvas(map, _sandSource));
AnsiConsole.MarkupLine($"[green]Total sand blocks: [yellow]{sandBlocksCount}[/][/]");
if (display)
{
AnsiConsole.Write(GenerateCanvas(map, _sandSource));
AnsiConsole.MarkupLine($"[green]Total sand blocks: [yellow]{sandBlocksCount}[/][/]");
}
}
private static bool GenerateSand(CellType[,] map, Canvas canvas, in Point sandSource)

View File

@@ -74,7 +74,7 @@ public class Day15 : Day
{
public override int Number => 15;
public override string Name => "Beacon Exclusion Zone";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
const int targetY = 2_000_000;
@@ -129,10 +129,13 @@ public class Day15 : Day
totalCovered -= beaconsOnTargetY.Count;
// Print total covered columns on line Y
AnsiConsole.MarkupLine($"[green]Number of positions that cannot contain a beacon: [yellow]{totalCovered}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of positions that cannot contain a beacon: [yellow]{totalCovered}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
const int xMin = 0;
const int xMax = 4_000_000;
@@ -213,7 +216,10 @@ public class Day15 : Day
var tuningFrequency = finalPoint.X * (long) 4_000_000 + finalPoint.Y;
AnsiConsole.MarkupLine($"[green]Tuning frequency: [yellow]{tuningFrequency}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Tuning frequency: [yellow]{tuningFrequency}[/][/]");
}
}
private static IList<SensorBeaconPair> ParsePairs()

View File

@@ -18,10 +18,10 @@ public enum Outcome : long
public class Day2 : Day
{
public override int Number { get; } = 2;
public override string Name { get; } = "Rock Paper Scissors";
public override void RunPart1()
public override int Number => 2;
public override string Name => "Rock Paper Scissors";
public override void RunPart1(bool display = true)
{
long score = 0;
@@ -33,14 +33,17 @@ public class Day2 : Day
score += (long) selfChoice;
score += (long) ComputeOutcome(adversaryChoice, selfChoice);
}
AnsiConsole.MarkupLine($"[green]Total score: [yellow]{score}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Total score: [yellow]{score}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
long score = 0;
foreach (var line in Input.ReadAllLines())
{
var adversaryChoice = AdversaryInputToChoice(line[0]);
@@ -50,8 +53,11 @@ public class Day2 : Day
score += (long) selfChoice;
score += (long) desiredOutcome;
}
AnsiConsole.MarkupLine($"[green]Total score: [yellow]{score}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Total score: [yellow]{score}[/][/]");
}
}
private Outcome ComputeOutcome(Choice adversary, Choice self) => (adversary, self) switch
@@ -83,7 +89,7 @@ public class Day2 : Day
'C' => Choice.Scissors,
_ => throw new ArgumentException("Invalid input")
};
private Choice SelfInputToChoice(char input) => input switch
{
'X' => Choice.Rock,

View File

@@ -7,7 +7,7 @@ public class Day3 : Day
public override int Number => 3;
public override string Name => "Rucksack Reorganization";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
long sum = 0;
@@ -22,10 +22,13 @@ public class Day3 : Day
sum += CharToPriority(common);
}
AnsiConsole.MarkupLine($"[green]Sum of priorities is: [yellow]{sum}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Sum of priorities is: [yellow]{sum}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
long sum = 0;
@@ -40,10 +43,13 @@ public class Day3 : Day
sum += CharToPriority(common);
}
AnsiConsole.MarkupLine($"[green]Sum of priorities is: [yellow]{sum}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Sum of priorities is: [yellow]{sum}[/][/]");
}
}
private int CharToPriority(char c)
private static int CharToPriority(char c)
{
if (char.IsLower(c))
{

View File

@@ -6,7 +6,7 @@ public class Day4 : Day
{
public override int Number => 4;
public override string Name => "Camp Cleanup";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
int overlaps = 0;
foreach (var line in Input.ReadAllLines())
@@ -18,7 +18,7 @@ public class Day4 : Day
var firstSection = sections[0];
var secondSection = sections[1];
// Check if first section contains second section
if (firstSection.Start <= secondSection.Start && firstSection.End >= secondSection.End)
{
@@ -30,11 +30,14 @@ public class Day4 : Day
overlaps++;
}
}
AnsiConsole.MarkupLine($"[green]Overlapping sections: [yellow]{overlaps}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Overlapping sections: [yellow]{overlaps}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
int overlaps = 0;
foreach (var line in Input.ReadAllLines())
@@ -46,15 +49,18 @@ public class Day4 : Day
var firstSection = sections[0];
var secondSection = sections[1];
// Check if first section overlaps second
if (firstSection.Start <= secondSection.End && firstSection.End >= secondSection.Start)
{
overlaps++;
}
}
AnsiConsole.MarkupLine($"[green]Overlapping sections: [yellow]{overlaps}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Overlapping sections: [yellow]{overlaps}[/][/]");
}
}
#region Input

View File

@@ -9,7 +9,7 @@ public class Day5 : Day
private IDictionary<int, Stack<char>>? _stacks;
public override void RunPart1()
public override void RunPart1(bool display = true)
{
_stacks = InitStacks();
@@ -26,14 +26,17 @@ public class Day5 : Day
}
}
for (int i = 1; i <= 9; i++)
if (display)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
for (int i = 1; i <= 9; i++)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
}
AnsiConsole.WriteLine();
}
AnsiConsole.WriteLine();
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
_stacks = InitStacks();
@@ -53,11 +56,14 @@ public class Day5 : Day
}
}
for (int i = 1; i <= 9; i++)
if (display)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
for (int i = 1; i <= 9; i++)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
}
AnsiConsole.WriteLine();
}
AnsiConsole.WriteLine();
}
#region Input

View File

@@ -6,7 +6,7 @@ public class Day6 : Day
{
public override int Number => 6;
public override string Name => "Tuning Trouble";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
int position = 0;
@@ -30,10 +30,13 @@ public class Day6 : Day
charStream.Dequeue();
}
AnsiConsole.MarkupLine($"[green]Position of start-of-packet marker is: [yellow]{position}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Position of start-of-packet marker is: [yellow]{position}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
const int length = 14;
int position = 0;
@@ -48,7 +51,7 @@ public class Day6 : Day
for (int i = length - 1; i < Input.Length; i++)
{
charStream.Enqueue(Input[i]);
// Check if all 14 chars are different
if (charStream.ToHashSet().Count == charStream.Count)
{
@@ -59,7 +62,10 @@ public class Day6 : Day
charStream.Dequeue();
}
AnsiConsole.MarkupLine($"[green]Position of start-of-message marker is: [yellow]{position}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Position of start-of-message marker is: [yellow]{position}[/][/]");
}
}
#region Input

View File

@@ -32,7 +32,7 @@ public class Day7 : Day
{
public override int Number => 7;
public override string Name => "No Space Left On Device";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
var fileSystem = ParseFileSystem();
@@ -42,10 +42,13 @@ public class Day7 : Day
.Where(d => d.Size < 100_000)
.Sum(d => d.Size);
AnsiConsole.MarkupLine($"[green]Total size: [yellow]{totalSize}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Total size: [yellow]{totalSize}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
const long fileSystemSpace = 70_000_000;
const long requiredSpace = 30_000_000;
@@ -63,7 +66,10 @@ public class Day7 : Day
.Where(d => d.Size > missingSpace)
.MinBy(d => d.Size);
AnsiConsole.MarkupLine($"[green]Directory to remove size: [yellow]{directoryToRemove!.Size}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Directory to remove size: [yellow]{directoryToRemove!.Size}[/][/]");
}
}
private static DirectoryEntry ParseFileSystem()

View File

@@ -6,7 +6,7 @@ public class Day8 : Day
{
public override int Number => 8;
public override string Name => "Treetop Tree House";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
var grid = CreateGrid();
@@ -92,10 +92,14 @@ public class Day8 : Day
}
}
AnsiConsole.MarkupLine($"[green]Total viewable trees: [yellow]{valid.Count}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Total viewable trees: [yellow]{valid.Count}[/][/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
var grid = CreateGrid();
@@ -116,7 +120,10 @@ public class Day8 : Day
}
}
AnsiConsole.MarkupLine($"[green]Max scenic score: [yellow]{maxScenicScore}[/][/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]Max scenic score: [yellow]{maxScenicScore}[/][/]");
}
}
private int ComputeScenicScore(int[,] grid, int i, int j, int size)

View File

@@ -7,7 +7,7 @@ public class Day9 : Day
public override int Number => 9;
public override string Name => "Rope Bridge";
public override void RunPart1()
public override void RunPart1(bool display = true)
{
// Start
(int x, int y) start = (0, 0);
@@ -49,10 +49,13 @@ public class Day9 : Day
}
}
AnsiConsole.MarkupLine($"[green]The tail visited [yellow]{tailVisitedPositions.Count}[/] unique positions[/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]The tail visited [yellow]{tailVisitedPositions.Count}[/] unique positions[/]");
}
}
public override void RunPart2()
public override void RunPart2(bool display = true)
{
const int tailSegments = 9;
@@ -130,7 +133,10 @@ public class Day9 : Day
}
}
AnsiConsole.MarkupLine($"[green]The tail visited [yellow]{tailVisitedPositions.Count}[/] unique positions[/]");
if (display)
{
AnsiConsole.MarkupLine($"[green]The tail visited [yellow]{tailVisitedPositions.Count}[/] unique positions[/]");
}
}
#region Input

View File

@@ -1,9 +1,18 @@

using System.Diagnostics;
using System.Diagnostics;
using System.Reflection;
using AdventOfCode;
using AdventOfCode.Days;
using BenchmarkDotNet.Running;
using Spectre.Console;
// Benchmark
if (args is ["--bench" or "-b"])
{
BenchmarkRunner.Run<DayBenchmark>();
Environment.Exit(0);
}
// Normal run
var days = Assembly.GetAssembly(typeof(Day))!.GetTypes()
.Where(t => t.IsAssignableTo(typeof(Day)) && t.GetConstructor(Type.EmptyTypes) != null && !t.IsAbstract)
.Select(t => (Day)Activator.CreateInstance(t)!);