Compare commits

17 Commits

Author SHA1 Message Date
b7b3192510 Add day 16 (not-working) 2024-06-03 14:51:50 +02:00
63c866f5a0 Add benchmark support using -b 2022-12-17 21:48:16 +01:00
147c348ee1 Add approximate run time using StopWatch 2022-12-17 19:30:38 +01:00
aa833569da Add day 15 2022-12-17 19:17:15 +01:00
0dfc6b59de Add day 14 2022-12-16 23:02:19 +01:00
331d064f66 Add day 13 2022-12-16 14:23:58 +01:00
4ff214e321 Update README.md 2022-12-15 21:42:10 +01:00
254f7f2e71 Add day 12 2022-12-15 21:28:42 +01:00
2b4d26e725 Add README 2022-12-15 10:00:26 +01:00
fd794bab16 Add day 11 part 2 2022-12-15 09:03:11 +01:00
a985d2e00c Add day 11 part 1 2022-12-14 13:39:01 +01:00
fe91c0f07a Add day 10 2022-12-12 15:21:30 +01:00
94e9159f8e Add day 9 2022-12-09 15:28:31 +01:00
ccdf246d5c Add day 8 2022-12-08 20:01:32 +01:00
5d6835b2e6 Add day 7 2022-12-08 15:51:56 +01:00
489ecc6d8d Add day 6 2022-12-06 15:51:21 +01:00
57002d439a Add day 5 2022-12-06 15:30:29 +01:00
24 changed files with 7480 additions and 287 deletions

4
.gitignore vendored
View File

@@ -3,4 +3,6 @@ obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
.idea/.idea.AdventOfCode/.idea
.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

287
Days/Day10.cs Normal file
View File

@@ -0,0 +1,287 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day10 : Day
{
public override int Number => 10;
public override string Name => "Cathode-Ray Tube";
public override void RunPart1(bool display = true)
{
int cycle = 1;
int x = 1;
long sum = 0;
// Increment sum when needed
void IncrementCycle()
{
cycle++;
// Check for signal stength at the start of a cycle
if ((cycle + 20) % 40 == 0)
{
sum += x * cycle;
}
}
foreach (var line in Input.ReadAllLines())
{
// noop
if (line == "noop")
{
// noop finished, go to next cycle
IncrementCycle();
}
// addx
else
{
var split = line.Split(' ');
var v = int.Parse(split[1]);
// Prepare addx
IncrementCycle();
// addx finished, add to x and then go to next cycle
x += v;
IncrementCycle();
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Sum of signal strengths: [yellow]{sum}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
// Setup the CRT
const char litPixel = '#';
const char darkPixel = '.';
const int rowCount = 6;
const int columnCount = 40;
var crt = new char[rowCount, columnCount];
var crtCanvas = new Canvas(columnCount, rowCount);
// Now cycle is the position where the CRT is drawing (need to offset by 1 in the grid)
int cycle = 1;
// x is the position of the sprite
int x = 1;
// Draw first pixel
crt[0, 0] = litPixel;
crtCanvas.SetPixel(0, 0, Color.Red);
// Increment sum when needed
void IncrementCycle()
{
cycle++;
// We're done drawing the crt
if (cycle > 240)
{
return;
}
// Draw a white or black pixel
int row = (cycle - 1) / columnCount;
int column = (cycle - 1) % columnCount;
// The CRT is drawing on the sprite
if (column == x - 1 || column == x || column == x + 1)
{
crt[row, column] = litPixel;
crtCanvas.SetPixel(column, row, (cycle + row) % 2 == 0 ? Color.Green : Color.Red);
}
else
{
crt[row, column] = darkPixel;
crtCanvas.SetPixel(column, row, Color.Black);
}
}
foreach (var line in Input.ReadAllLines())
{
// noop
if (line == "noop")
{
// noop finished, go to next cycle
IncrementCycle();
}
// addx
else
{
var split = line.Split(' ');
var v = int.Parse(split[1]);
// Prepare addx
IncrementCycle();
// addx finished, add to x and then go to next cycle
x += v;
IncrementCycle();
}
}
// Print the CRT
if (display)
{
AnsiConsole.Write(crtCanvas);
}
}
#region Input
public const string Input =
"""
noop
noop
addx 15
addx -10
noop
noop
addx 3
noop
noop
addx 7
addx 1
addx 4
addx -1
addx 1
addx 5
addx 1
noop
noop
addx 5
addx -1
noop
addx 3
noop
addx 3
addx -38
noop
addx 3
addx 2
addx 5
addx 2
addx 26
addx -21
addx -2
addx 5
addx 2
addx -14
addx 15
noop
addx 7
noop
addx 2
addx -22
addx 23
addx 2
addx 5
addx -40
noop
noop
addx 3
addx 2
noop
addx 24
addx -19
noop
noop
noop
addx 5
addx 5
addx 2
noop
noop
noop
noop
addx 7
noop
addx 3
noop
addx 3
addx -2
addx 2
addx 5
addx -38
noop
noop
noop
addx 5
addx 2
addx -1
addx 2
addx 30
addx -23
noop
noop
noop
noop
addx 3
addx 5
addx -11
addx 12
noop
addx 6
addx 1
noop
addx 4
addx 3
noop
addx -40
addx 4
addx 28
addx -27
addx 5
addx 2
addx 5
noop
noop
addx -2
addx 2
addx 5
addx 3
noop
addx 2
addx -25
addx 30
noop
addx 3
addx -2
addx 2
addx 5
addx -39
addx 29
addx -27
addx 5
noop
noop
noop
addx 4
noop
addx 1
addx 2
addx 5
addx 2
noop
noop
noop
noop
addx 5
addx 1
noop
addx 2
addx 5
addx -32
addx 34
noop
noop
noop
noop
""";
#endregion
}

233
Days/Day11.cs Normal file
View File

@@ -0,0 +1,233 @@
using System.Collections.Immutable;
using Spectre.Console;
namespace AdventOfCode.Days;
public class Monkey
{
public int Number { get; }
public long InspectionCount { get; private set; }
private readonly Queue<long> _items;
private readonly Func<long, long> _operation;
private readonly long _testDivider;
private readonly int _testFailMonkey;
private readonly int _testSuccessMonkey;
public Monkey(int number, IEnumerable<long> items, Func<long, long> operation, long testDivider, int testFailMonkey, int testSuccessMonkey)
{
Number = number;
_operation = operation;
_testDivider = testDivider;
_testFailMonkey = testFailMonkey;
_testSuccessMonkey = testSuccessMonkey;
InspectionCount = 0;
_items = new Queue<long>(items);
}
public void AddItem(long item)
{
_items.Enqueue(item);
}
public bool ThrowItem(IImmutableList<Monkey> monkeys, bool divideWorry = true)
{
// Return false if there's no item to throw
if (_items.Count < 1)
{
return false;
}
// Increment inspection count
InspectionCount++;
// Take next item to throw
var item = _items.Dequeue();
// Apply the operation on worry level
var newValue = _operation(item);
// Divide worry level by 3 before test
if (divideWorry)
{
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);
// Test is a success
if (newValue % _testDivider == 0)
{
monkeys[_testSuccessMonkey].AddItem(newValue);
}
// Test is a fail
else
{
monkeys[_testFailMonkey].AddItem(newValue);
}
return true;
}
}
public class Day11 : Day
{
public override int Number => 11;
public override string Name => "Monkey in the Middle";
public override void RunPart1(bool display = true)
{
const int roundsCount = 20;
var monkeys = ParseMonkeys();
// Do 20 rounds
for (int round = 0; round < roundsCount; round++)
{
foreach (var monkey in monkeys)
{
// Throw items while there's some
while (monkey.ThrowItem(monkeys)) { }
}
}
var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList();
if (display)
{
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
const int roundsCount = 10_000;
var monkeys = ParseMonkeys();
// Do 10 000 rounds
for (int round = 0; round < roundsCount; round++)
{
foreach (var monkey in monkeys)
{
// Throw items while there's some
while (monkey.ThrowItem(monkeys, false)) { }
}
}
var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList();
if (display)
{
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
}
}
private static IImmutableList<Monkey> ParseMonkeys()
{
var monkeys = new List<Monkey>();
// Split by monkey description
foreach (var monkey in Input.ReplaceLineEndings("\n").Split("\n\n"))
{
var split = monkey.Split('\n');
var numberLine = split[0];
var itemsLine = split[1];
var operationLine = split[2];
var testDividerLine = split[3];
var testSuccessLine = split[4];
var testFailLine = split[5];
// Monkey attributes
var number = int.Parse(numberLine[numberLine.LastIndexOf(' ')..^1]);
var items = itemsLine[(itemsLine.IndexOf(':') + 2)..].Split(", ").Select(long.Parse);
// Read operation
operationLine = operationLine[(operationLine.IndexOf('=') + 2)..];
long? rightOperand = operationLine.EndsWith("old") ? null : long.Parse(operationLine.Split('+', '*')[1].Trim());
Func<long, long> operation = operationLine.Contains('+') switch
{
true => rightOperand is null
? old => old + old
: old => old + (int)rightOperand,
false => rightOperand is null
? old => old * old
: old => old * (int)rightOperand
};
var testDivider = long.Parse(testDividerLine[testDividerLine.LastIndexOf(' ')..]);
var testSuccessMonkey = int.Parse(testSuccessLine[testSuccessLine.LastIndexOf(' ')..]);
var testFailMonkey = int.Parse(testFailLine[testFailLine.LastIndexOf(' ')..]);
monkeys.Add(new Monkey(number, items, operation, testDivider, testFailMonkey, testSuccessMonkey));
}
return monkeys.ToImmutableList();
}
#region Input
public const string Input =
"""
Monkey 0:
Starting items: 89, 95, 92, 64, 87, 68
Operation: new = old * 11
Test: divisible by 2
If true: throw to monkey 7
If false: throw to monkey 4
Monkey 1:
Starting items: 87, 67
Operation: new = old + 1
Test: divisible by 13
If true: throw to monkey 3
If false: throw to monkey 6
Monkey 2:
Starting items: 95, 79, 92, 82, 60
Operation: new = old + 6
Test: divisible by 3
If true: throw to monkey 1
If false: throw to monkey 6
Monkey 3:
Starting items: 67, 97, 56
Operation: new = old * old
Test: divisible by 17
If true: throw to monkey 7
If false: throw to monkey 0
Monkey 4:
Starting items: 80, 68, 87, 94, 61, 59, 50, 68
Operation: new = old * 7
Test: divisible by 19
If true: throw to monkey 5
If false: throw to monkey 2
Monkey 5:
Starting items: 73, 51, 76, 59
Operation: new = old + 8
Test: divisible by 7
If true: throw to monkey 2
If false: throw to monkey 1
Monkey 6:
Starting items: 92
Operation: new = old + 5
Test: divisible by 11
If true: throw to monkey 3
If false: throw to monkey 0
Monkey 7:
Starting items: 99, 76, 78, 76, 79, 90, 89
Operation: new = old + 7
Test: divisible by 5
If true: throw to monkey 4
If false: throw to monkey 5
""";
#endregion
}

333
Days/Day12.cs Normal file
View File

@@ -0,0 +1,333 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day12 : Day
{
public override int Number => 12;
public override string Name => "Hill Climbing Algorithm";
public const int EndElevation = 25;
// Color map of elevation: blue -> green -> yellow -> orange -> red
private readonly Color[] _colorMap =
{
Color.Blue1,
Color.DodgerBlue1,
Color.DeepSkyBlue1,
Color.Turquoise2,
Color.Cyan1,
Color.Cyan2,
Color.MediumSpringGreen,
Color.SpringGreen1,
Color.SpringGreen2_1,
Color.Green1,
Color.DarkOliveGreen2,
Color.GreenYellow,
Color.DarkOliveGreen1,
Color.Yellow2,
Color.Khaki1,
Color.Yellow1,
Color.NavajoWhite1,
Color.LightGoldenrod2_1,
Color.Gold1,
Color.SandyBrown,
Color.Orange1,
Color.DarkOrange,
Color.OrangeRed1,
Color.IndianRed1,
Color.HotPink,
Color.MediumOrchid1_1
};
private (int x, int y) _end;
private (int x, int y) _start;
public override void RunPart1(bool display = true)
{
var map = ParseMap();
var canvas = DrawMap(map);
// Test all possible solutions
var minimumPathLength = ExplorePath(map);
// Draw solution path
foreach (var (x, y) in minimumPathLength.path)
{
canvas.SetPixel(x, y, Color.White);
}
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var map = ParseMap();
var canvas = DrawMap(map);
// Test all possible solutions
var minimumPathLength = FindNearestStart(map);
// Draw solution path
foreach (var (x, y) in minimumPathLength.path)
{
canvas.SetPixel(x, y, Color.White);
}
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine($"[green]Minimum path length: [yellow]{minimumPathLength.length}[/][/]");
}
}
private (int length, List<(int x, int y)> path) ExplorePath(byte[,] map)
{
var height = map.GetLength(0);
var width = map.GetLength(1);
// Store seen positions with number of steps to reach this position
var exploredPositions = new Dictionary<(int x, int y), int>();
var toExplore = new Queue<(int x, int y, int elevation, int steps, List<(int x, int y)> path)>();
var pathLengths = new List<(int length, List<(int x, int y)> path)>();
toExplore.Enqueue((_start.x, _start.y, 0, 0, new()));
// Explore all possible path
while (toExplore.Count > 0)
{
var (x, y, previousElevation, steps, path) = toExplore.Dequeue();
// If we went out of bound
if (x < 0 || x >= width || y < 0 || y >= height)
{
continue;
}
// If new elevation is too high
var newElevation = map[y, x];
if (newElevation - previousElevation > 1)
{
continue;
}
// If new path is not better than old path, just skip
if (exploredPositions.TryGetValue((x, y), out var oldSteps))
{
if (oldSteps <= steps)
{
continue;
}
}
// Mark this position as explored and store required number of steps to reach it
exploredPositions[(x, y)] = steps;
// Update path
var newPath = new List<(int x, int y)>(path) { (x, y) };
// If we found the end, note that we could end the search here since it's a bfs, there can't be
// any shorter path to this point
if ((x, y) == _end)
{
pathLengths.Add((steps, newPath));
continue;
}
var nextPositions = new (int x, int y)[]
{
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)
};
foreach (var nextPosition in nextPositions)
{
toExplore.Enqueue((nextPosition.x, nextPosition.y, newElevation, steps + 1, newPath));
}
}
return pathLengths.MinBy(p => p.length);
}
private (int length, List<(int x, int y)> path) FindNearestStart(byte[,] map)
{
var height = map.GetLength(0);
var width = map.GetLength(1);
// Store seen positions with number of steps to reach this position
var exploredPositions = new Dictionary<(int x, int y), int>();
var toExplore = new Queue<(int x, int y, int elevation, int steps, List<(int x, int y)> path)>();
var pathLengths = new List<(int length, List<(int x, int y)> path)>();
toExplore.Enqueue((_end.x, _end.y, EndElevation, 0, new()));
// Explore all possible path
while (toExplore.Count > 0)
{
var (x, y, previousElevation, steps, path) = toExplore.Dequeue();
// If we went out of bound
if (x < 0 || x >= width || y < 0 || y >= height)
{
continue;
}
// If new elevation is too low, skip
var newElevation = map[y, x];
if (previousElevation - newElevation > 1)
{
continue;
}
// If new path is not better than old path, just skip
if (exploredPositions.TryGetValue((x, y), out var oldSteps))
{
if (oldSteps <= steps)
{
continue;
}
}
// Mark this position as explored and store required number of steps to reach it
exploredPositions[(x, y)] = steps;
// Update path
var newPath = new List<(int x, int y)>(path) { (x, y) };
// If we found a possible start, same as in the 1st part, we could stop here
if (newElevation == 0)
{
pathLengths.Add((steps, newPath));
continue;
}
var nextPositions = new (int x, int y)[]
{
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)
};
foreach (var nextPosition in nextPositions)
{
toExplore.Enqueue((nextPosition.x, nextPosition.y, newElevation, steps + 1, newPath));
}
}
return pathLengths.MinBy(p => p.length);
}
private byte[,] ParseMap()
{
var lines = Input.ReadAllLines().ToArray();
var lineCount = lines.Length;
var columnCount = lines[0].Length;
var map = new byte[lineCount, columnCount];
for (int i = 0; i < lineCount; i++)
{
var line = lines[i];
for (int j = 0; j < columnCount; j++)
{
var elevation = line[j];
map[i, j] = elevation switch
{
'S' => 0,
'E' => EndElevation,
_ => (byte) (elevation - 'a')
};
// Store the end
if (elevation == 'E')
{
_end = (j, i);
}
// Store the start
if (elevation == 'S')
{
_start = (j, i);
}
}
}
return map;
}
private Canvas DrawMap(byte[,] map)
{
var height = map.GetLength(0);
var width = map.GetLength(1);
var canvas = new Canvas(width, height);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
canvas.SetPixel(x, y, _colorMap[map[y, x]]);
}
}
return canvas;
}
#region Input
public const string Input =
"""
abccccccaaccaaccccaaaaacccccaaaaccccccccccccccccccccccccccccccccaaaaaaaaaaaaaaaaaaaccccccccccccccccaaaccccccccccccaacccccccccccccccccccccccccccccccccccccccccaaaa
abaaaaccaaaaaccccaaaaaccccccaaaaccccccccccccccccccccaaacccccccccccaaaaaaaaaaaaaaaaaaccccccccccccccccaaaaccccccaaacaaccccccccccccccccccccccccccccccccccccccccaaaaa
abaaacccaaaaaaaacaaaaaacccccaaaaccccccccccccccccccccaaaaacccccccccaaaaaaaaaaaaaaaaacccccccccaaccccaaaaaacccccccaaaaaccccaaccccccccccccccacccccccccccccccccccaaaaa
abaaacccccaaaaaccccaaaaccccccaaacccccccccccccccccccaaaaaccccccccccaaaaaacacaaaaaacccccccccccaaccccaaaaacccccccccaaaaaaccaaaaaaccccccccccaaaccccacccccccccccaaaaaa
abaacccccaaaaaccccaacccccccccccccccaaaaacccccccccccaaaaacccccccccaaaaaaaaccaaaaaaacccccccaaaaaaaaccaaaaacccccccaaaaaaaccaaaaacccccccccccaaacccaaaccccccccccccccaa
abaaacccaaacaacccccccccccccccccccccaaaaaccccccccccccaaaaacccccccaaaaaaaaaccaaccaaacccccccaaaaaaaaccaacccccccccaaaaaaccaaaaaaccccccccccccaaaacaaaaccccccccccccccaa
abaaacccccccaaccccccccccccccccccccaaaaaaccccccccccccaaccccccaacccaaaccaaaaccccccaacccccccccaaaacccccccccccccccaacaaaccaaaaaaaccccccccccccajjjjjjjcccccccccccccccc
abcaacccccccccccccccccccccccccccccaaaaaaccccccccccccccccccccaaaaccccccaaaaccccccccccccccaacaaaaaccccccccccccccccccaaccccaaaaaacccccccccccjjjjjjjjjcccccaaaccccccc
abccccccccccccccccccccccccccccccccaaaaaaccaaccccccccccccccaaaaaacccccccaaacccccccccccaacaaaaaaaaccccccccccccccccccccccccaaccaaccccccccaiijjjjojjjjcccccaaacaccccc
abcccccccccccccccccccccccaaacccccccaaacacaaacccccccccccccccaaaaccccaaccccccccccccccccaaaaaaacccaccccccccccccccccccccccccaacccccccccccaiiijjooooojjkccaaaaaaaacccc
abccccccccccccccccccccccaaaaccccccccccaaaaaccccccccccccccccaaaaacccaaaaaccccccccccccccaaaaaacccccccccccccccccccccccccccccccccccccciiiiiiiioooooookkkcaaaaaaaacccc
abccccccccccccccccccccccaaaaccccccccccaaaaaaaacccccccccccccaacaaccaaaaacccccccaaacccaaaaaaaaccccccccccccccccccccccccccccccccccchiiiiiiiiooooouoookkkccaaaaaaccccc
abcccccccccaaccccccccccccaaaccccccccccccaaaaacccccccccccccccccccccaaaaaccccccaaaacccaaaaacaacccccccccccccaacaacccccccccccccccchhhiiiinnnooouuuuoookkkccaaaaaccccc
abcccccccccaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccaaaaacccccaaaaccccccaaccccccccccccccccaaaaacccccccccccccccchhhnnnnnnnnouuuuuuppkkkkaaaaaaccccc
abccccccaaaaaaaacccaaccccccccccccccccccaacaaccaacaaccccccccccccccccaacccccccccaaaccccccaacccccccccccccccaaaaacccccccccccccccchhhnnnnnnnnntuuxuuupppkkkkkacccccccc
abccccccaaaaaaaacacaaaacccccccccccccccccccaaccaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccaacccccchhhnnnnttttttuxxxuuppppkkkkkcccccccc
abcccccccaaaaaaccaaaaaaccccccccccaaccccccccccaaaaaccccccccccccccccccccccccaaacccccccccccccccccccccccccccccaaaaccaaccaaacccaaahhhnnntttttttuxxxxuupppppllllccccccc
abcccccccaaaaaacccaaaacccccccccaaaaaaccccccccaaaaaacccccccccccccccccccccccaaacccccccccccccccccccccccccccccacccccaaaaaaacaaaaahhhppntttxxxxxxxxuuuuvpppplllccccccc
abcccccccaaaaaacccaaaacccccccccaaaaaacccccaaaaaaaaaccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaaccccccaacaaaaaaccaaaaahhhpppttxxxxxxxxyuuvvvvvppplllcccccc
abcccccccaaccaacccaacaccaaaaccccaaaaacccccaaaaaaaaaccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaacaaaaaaaccaaaaaaaaaaaaahhppptttxxxxxxyyyyyyvvvppplllcccccc
SbccccccccccccccccccccccaaaacccaaaaacccccccaaaaaaaaacaaaccccccccaacccccccaaaaaccccccccaaaaacccccccccaaaaaaaaaaaaaaaaaaaaaaaaacgggpppttxxxxEzzyyyyyvvvqqqlllcccccc
abccccccccccccccccccccccaaaacccaaaaacccccccaaaaaaaaccaaaccccccccaaacaaccaaaaaaccccccccaaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaacgggpppsssxxxyyyyyyvvvvvqqlllccccccc
abcccaaaccccccccccccccccaaaccccccccccccccccaaaaaaaaaaaaaccccccccaaaaaaccaaaaaacccccccaaaaaacccaaaccaaaaaccaaaaaaaaaaaacccccccccgggppssswwyyyyyyvvvvqqqqlllccccccc
abcaaaaaccccccccccccccccccccccccccccccccccaaaaaaaaaaaaacccccccaaaaaaacccaccaaacccccccaaaaaacccaaacccaaaaaaaaaaaccccaaacccaaaaacgggppsswwwyyyyyyvvqqqqqlllcccccccc
abcaaaaaaccccccccccccccccccccccccccccccccccaaccaaaaaaaaaaaccccaaaaaaacccccccccccccccccaaaaacccaaacaaaacaaaaaaaaccccaaacccaaaaacggpppsswwwywwyyyvvqqqmmmlccccccccc
abcaaaaaacccccccaacaaccccccccccccccccccccccccccaaaaaaaaaaaccccccaaaaacccccccccccccccccaaaccaaaaaaaaaaacccccccaacccccccccaaaaaacggpppsswwwwwwwwyvvqqqmmmcccccccccc
abcaaaaaccccccccaaaaaccccccccccccccccccccccccccccaaaaaaaacccccccaacaaacccccccccccccccccccccaaaaaaaaaccccccccccccccccccccaaaaaagggoossswwwwrrwwwvvqqmmmccccccccccc
abcaaaaacccccccaaaaaccccccccccccccccccccccccccccaaaaaaacccccccccaaccccccccccccccccccccccccccaaaaaaacccccccccccaaaccccccccaaaaagggooosssssrrrrwwwvqqmmmcccaacccccc
abcccccccccccccaaaaaaccccccccccccccccccccaacccccccccaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccccccccccaaaaccccccaaaccgggooosssssrrrrrwwrrqmmmcccaacccccc
abcccccccccccccccaaaacccccccccccccccccccaaaacccccccacaaacccccccccccccccccccccccccccccccccccccaaaaaaacccccccccaaaaaacccccccccccgffoooooosoonrrrrrrrrmmmccaaaaacccc
abcccccccccccccccaccccccccccccccccccccccaaaacccccccaaaaacccccccccccccccccccccccccccccccccccccaaacaaacccccccccaaaaacccccccccccccfffoooooooonnnrrrrrmmmddcaaaaacccc
abccccccccccccccccccccccccccccccccccccccaaaaccccccccaaaaacccccccccccccccccccccccccaaaccccccccaacccccccccccccccaaaaaccccccccccccffffoooooonnnnnnrnnmmmdddaaaaacccc
abcccccccccccccccccccccccccccccccccccccccccccccccccaaaaaacccccccccccccccccaaaaaccaaaacccccccccccccccccccccccccaacccccccccccccccfffffffffeeeennnnnnmmdddaaaacccccc
abcccccccaaaccccccccaccccccccccccccccccccccccccccccaaaaccccccccccccaaaccccaaaaaccaaaaccccccccccccccccccccccccccccccccccccccccccccfffffffeeeeennnnnmddddaaaaaccccc
abcccaaccaaacccccaaaacccccaacccccccccccccccccccccccccaaacccccccccccaaacccaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccffffeeeeeeeedddddddcccaacccccc
abcccaaaaaaacccccaaaaaaccaaacccccccccccccccccccccccccccacccccccccccaaaaccaaaaaaccccccccccccccccccccccccccaacccccccccaaaccccccccccccccaaaaaaeeeeedddddcccccccccccc
abcccaaaaaacccccccaaaacccaaacaaaccccaaaacccccccccaaacaaaccccccaacccaaaacaaaaaaacccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccaaaaeeddddccccccccccccc
abccccaaaaaaaacccaaaaaaaaaaaaaaaccccaaaacccccccccaaaaaaacccccaaacccaaaaaaaaaacccccccccccccccccccccccaaacaaaccccccccaaaaccccccccccccccccccccaaaccccccccccccccaaaca
abcccaaaaaaaaacccaacaaaaaaaaaaacccccaaaaccccccccccaaaaaacaaacaaacaaaaaaaaaacccccccccccccccaaacccccccaaaaaaaaaaccccccaaaccccccccccccccccccccaacccccccccccccccaaaaa
abcccaaaaaaaacccccccccccaaaaaacccccccaacccccccccccaaaaaaaaaaaaaaaaaaaaaaaaccccccccccccccccaaaacccccccaaaaaaaaacccccccccccccccccccccccccccccaaacccccccccccccccaaaa
abccaaaaaaacccccccccccccaaaaaaacccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccaaaacccccccaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccaaaaa
""";
#endregion
}

731
Days/Day13.cs Normal file
View File

@@ -0,0 +1,731 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public abstract class PacketElement : IEquatable<PacketElement>, IComparable<PacketElement>
{
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((PacketElement) obj);
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
public static bool operator ==(PacketElement left, PacketElement right)
{
return left.Equals(right);
}
public static bool operator !=(PacketElement left, PacketElement right)
{
return !(left == right);
}
public static bool operator <(PacketElement left, PacketElement right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >(PacketElement left, PacketElement right)
{
return left.CompareTo(right) > 0;
}
public bool Equals(PacketElement? other)
{
return other is not null && (this, other) switch
{
(IntegerElement leftInteger, IntegerElement rightInteger) => leftInteger.Value == rightInteger.Value,
(ListElement leftList, IntegerElement rightInteger) => leftList.Elements is [var x] && x == rightInteger,
(IntegerElement leftInteger, ListElement rightList) => rightList.Elements is [var x] && x == leftInteger,
(ListElement leftList, ListElement rightList) => leftList == rightList,
_ => throw new ArgumentException("Can only compare lists and integers")
};
}
public int CompareTo(PacketElement? other)
{
return (this, other) switch
{
(IntegerElement leftInteger, IntegerElement rightInteger) => leftInteger.Value.CompareTo(rightInteger.Value),
(ListElement leftList, IntegerElement rightInteger) => leftList.CompareTo(new ListElement(new PacketElement[] { rightInteger })),
(IntegerElement leftInteger, ListElement rightList) => -rightList.CompareTo(new ListElement(new PacketElement[] { leftInteger })),
(ListElement leftList, ListElement rightList) => leftList.CompareTo(rightList),
_ => throw new ArgumentException("Can only compare lists and integers")
};
}
}
public class ListElement : PacketElement, IEquatable<ListElement>, IComparable<ListElement>
{
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((ListElement) obj);
}
public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), Elements);
}
public IList<PacketElement> Elements { get; }
public int Count => Elements.Count;
public ListElement(IList<PacketElement> elements)
{
Elements = elements;
}
public static bool operator ==(ListElement left, ListElement right)
{
return left.Equals(right);
}
public static bool operator !=(ListElement left, ListElement right)
{
return !(left == right);
}
public static bool operator <(ListElement left, ListElement right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >(ListElement left, ListElement right)
{
return left.CompareTo(right) > 0;
}
public bool Equals(ListElement? other)
{
return other is not null && Count == other.Count && Elements.Zip(other.Elements).All(t => t.First == t.Second);
}
public int CompareTo(ListElement? other)
{
if (other is null)
{
throw new ArgumentException("Other can't be null");
}
// Compare elements by elements
for (int i = 0; i < other.Count; i++)
{
// If there's no element in this list anymore, it's that it's lower
if (i >= Count)
{
return -1;
}
// If the two next values aren't equal, return the result, else continue
var compare = Elements[i].CompareTo(other.Elements[i]);
if (compare != 0)
{
return compare;
}
}
// If there's still more elements in this list, it means that it's bigger, else they are equal
return other.Count != Count ? 1 : 0;
}
}
public class IntegerElement : PacketElement
{
public int Value { get; }
public IntegerElement(int value)
{
Value = value;
}
}
public class Day13 : Day
{
public override int Number => 13;
public override string Name => "Distress Signal";
public override void RunPart1(bool display = true)
{
var pairs = ParsePacketPairs();
var sum = 0;
for (int i = 0; i < pairs.Count; i++)
{
var pair = pairs[i];
if (pair.left < pair.right)
{
sum += i + 1;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Right order pair indices sum: [yellow]{sum}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var packets = ParsePackets();
// Add divider packets
var firstDivider = new ListElement(new PacketElement[] { new ListElement(new PacketElement[] { new IntegerElement(2) }) });
var lastDivider = new ListElement(new PacketElement[] { new ListElement(new PacketElement[] { new IntegerElement(6) }) });
packets.Add(firstDivider);
packets.Add(lastDivider);
var orderedPackets = packets.Order().ToList();
var firstDividerIndex = orderedPackets.IndexOf(firstDivider) + 1;
var lastDividerIndex = orderedPackets.IndexOf(lastDivider) + 1;
if (display)
{
AnsiConsole.MarkupLine($"[green]Decoder key is: [yellow]{firstDividerIndex * lastDividerIndex}[/][/]");
}
}
private static PacketElement ReadElement(ref ReadOnlySpan<char> packet)
{
// This is an integer
if (packet[0] != '[')
{
return ReadInteger(ref packet);
}
// This is a list packet
return ReadList(ref packet);
}
private static ListElement ReadList(ref ReadOnlySpan<char> packet)
{
var list = new List<PacketElement>();
while (packet[0] != ']')
{
// Skip delimiter
packet = packet[1..];
// If it's an empty list
if (packet[0] == ']')
{
break;
}
list.Add(ReadElement(ref packet));
}
// Skip closing bracket
packet = packet[1..];
return new ListElement(list);
}
private static IntegerElement ReadInteger(ref ReadOnlySpan<char> packet)
{
var intEnd = packet.IndexOfAny(',', ']');
var element = new IntegerElement(int.Parse(packet[..intEnd]));
packet = packet[intEnd..];
return element;
}
private static IList<(PacketElement left, PacketElement right)> ParsePacketPairs()
{
var pairs = new List<(PacketElement, PacketElement)>();
foreach (var pair in Input.ReplaceLineEndings("\n").Split("\n\n"))
{
var split = pair.Split('\n');
var leftSpan = split[0].AsSpan();
var rightSpan = split[1].AsSpan();
pairs.Add((ReadElement(ref leftSpan), ReadElement(ref rightSpan)));
}
return pairs;
}
private static IList<PacketElement> ParsePackets()
{
var packets = new List<PacketElement>();
foreach (var packet in Input.ReadAllLines().Where(l => !string.IsNullOrWhiteSpace(l)))
{
var packetSpan = packet.AsSpan();
packets.Add(ReadElement(ref packetSpan));
}
return packets;
}
#region Input
public const string Input =
"""
[[5,[[3,0]],[0,[8,6,9],2,9],[5,6,[2,8,3],[0]],[6,2,[2,6,8],10]]]
[[6,4,[2,[2,2],8,[3,7,0,6,2]]],[4,10]]
[[[6,[10,9,7]],9,[9,[9,0,8,3],[0],3],[8,1]],[2,10,9],[[0,6,[4]],2,[2,3,[6,7,0],[1,4,2]],[[3,7,2],[],0],9],[],[[]]]
[[1,[1,10]]]
[[2,3,[]],[7,[[6,9,9,1,6],[0,3],10,3,[5]],[[]],[9,[],[1,0,0,1,1]]],[7,[1,[3,0],[7,10,8,5,0],2,1],4,7,3],[[5],6,4],[9,3,[4,[0,7,9,9],5,[2,0],[]],[6,[],[4,9]]]]
[[2,[[3,4,7],[7,2,2,6],[8,9,7,7,6],[7,8,1,6,1],[]],[],8]]
[[4,[[9,8,1],2],10,6,[[],[],7]]]
[[9,4,10],[0,[1,[10,4,6],[1],8],[[6,2,7,2,4],[9,3,5,6],[0,3,7],10],3],[[[5,4],2,10],2,9,4,[[6,7,2,3],[6]]],[],[]]
[[0,1],[[7,[10,0,8,1],1,4]],[]]
[[1,3,2,3],[1,[[],7,[6,5,8,7,9],[0,2]],[8],5,[]],[[7,8,[],[8,9,4]],[2]]]
[[7,[[6]],[4,9]]]
[[10],[],[[10,[10,10,5,2,1],[10],5],[4,4],[[2,1],[9]],6],[6,8]]
[[[[],[2,3,7],4],0],[[[6,5,10,2,6],10,[2,7],5,5],7,8,[0]],[[10,1,3,3,[7]],0],[]]
[[[[6,2,2,8],[7,4,9,4],3,[0]],7,10]]
[[6,5,5,1],[8],[]]
[[1,[]],[10],[10,[8,[4]],6,1],[5]]
[[[[1,1,2,4],[7,8,8,7],5,[9,1,7,0,8],[2,10,10,4]],10,[7,[6,10],[6,10,6,9],[0,8,10],7]],[8,[[],[],[1,3,0,5,10],[7,0,7]],1],[]]
[[6,3,[],5],[]]
[[[3],[2,[],[1,10,5,5],[1,0,3,3,1]]]]
[[[6,5,[4]]],[5,10,5,3],[6],[10]]
[[[[],[5,0,8,5,4],[2],0,[]],7,6,10,[7,1,10,9]],[]]
[[[8,[1,2,3]]],[8],[6,9,[3,1,1,[10,10,3,10,0]],3,0],[[[8,7]]]]
[[0,[[0],5,[6,3,3],[10,3,10,9]],4]]
[[],[5],[8],[[[10,8,10,5,3],[3,7,10,9,8],0],[[],[]]]]
[[],[10,[7,3,[6],7],[9,[3],[8],7,[1]],10],[6,9,[9,3],[[4,8,1],[10,1,4,7],7],10],[[],[3]]]
[[[6],5,6,10,6],[[]],[1,[6,10],8,3],[1]]
[[1,3],[10,[2],8,1,[6,6,[5],5,[2]]],[[4]],[],[]]
[[[],[1,0,[8],8,[0,3,6]],1],[[[6,1],8,3,1],1,[6,[6,9,3,8,7]],10,[5,[4]]]]
[[9,[6,2,[],[3,0,2,7]],0],[[[5,4,0],0,[2],[7,3,2,5,1]],9,3]]
[[2,[7,[5,2,4],8,5,[3,0,4,5,4]],0,8]]
[[8,6,3,[[10,1,1,7]],8]]
[[[9,2,5],10,5]]
[[],[6],[[[3,6,3,9]],[[2,0],7,1,[10,10,4,4,10]]]]
[[4,[[6,8,4,9,2],[],5,[10,1]],1,6],[[[4,2,5],4]],[[3,6]],[7,8,[[5,8,9,10],1,[6,8],1,7]]]
[[[[],10,7],[],[1,[]],8,[9,0]],[0,[[6],3,1,[0,7,5]],[[7,6,3,9,3],4,4],[],0],[],[9,2,[9,1,[0,9,4,6],[9,2],10],9]]
[[],[2,5,6,5,8]]
[[[[4,4],5,[7],3,[8,8,4]],2],[]]
[[[[6,5,4,7,1],[0,9,9]],[[7,3,7,6,10],3,[6,4,9,4]],[1,[],[]]],[[7,5,[2,4,1,1]],2,4],[],[[[4,7],[1,7,9],5,[]],4,[[7,5,1,9,10],2,5,[1,2,0,9,9]]],[9,[]]]
[[7,[[8,10,9,4,5],[1,3]],1],[[[1,1],2],[[3]],[[7,9,6,6,8],4,[5]],7],[3],[[9,[3,9],[3,1,0,9,2]],4,5,9,[[1]]]]
[[[4,[9],5],[[2],8,[5,7,0,0],0,9],[[2,1],[],7,[7,1],2],4,7],[[[4,7,0,10,2],[5,5,0,3,6],[10,6,3,3],4,8],2,[[1]],9,9]]
[[[[6,2,4,0]],[],[[8,3,1,5,5],1,7,4,2],5,1]]
[[[],0],[],[4,[[1,6],2,[8,4,1,3,10]],[5,0,[10,1,0]],8,[2,[10,8,4],[6,2,7,10,10],[8,2,4,4],[]]],[[],6],[[4,5,[2],[10,2,2,1],[4,6,5,10]],[5,[],9,[1]],[]]]
[[9]]
[[[],8],[7,[6,4]],[5]]
[[],[[3,5,[1],3,[3]],[5],6,[[7,2,6,9],[1,0,0,1]]],[[[5,5,2,0,10],10,7,8,7],5,7,7,[[],1,[6]]],[[]]]
[[[5,8,10,[9,1,3,2,4],[6,7,0,7,6]],3,[[7],3,9,4,[9]]]]
[[3,1,4,[[6]],[[4,6],1,[4]]],[0],[3,[],7]]
[[7]]
[[4,[[5]],[10,8,5,0]],[4]]
[[7,6,10,[[1],8,0,[10,5,1]]],[[[2,1,6],9,9,[4],9]],[]]
[[7,0,5,3,1],[],[[0,9,[8,4,9]],[7,[10,9,4,1,7],2,6],10,[],10],[]]
[[1,[],[],6,[[],10,3]]]
[[[[1,6]]],[[[5,3,7],[],[10,9,7,3,3],0,[]],3,10,5],[],[10,[2]]]
[[[[1,5],5],[[6],[3,2],9,[2,0,8]],[9,[6,9,4],8,0,6]],[[[8],8,10],0,[],6,[[2,7,8],0,9]],[7,1],[[[0],[9,5,9]],[[2,10]],[]]]
[[1,7,[[9],8,[1,1,8]]],[[[9,10,2,0,1],10],0,[7,[10,10],10],5],[7,1],[9,[[],[7,10]]],[[2,9,8,[0,0],[10,9,4,1]],[5],[[8,6]]]]
[[[[4,7,4],[],6,[5,4]],[],[7,[],[],3],[[9,3,5,1,10],[],[7,2]]],[[6,1],3,[[],[3,2],[],[3],[8,7,3,9]]]]
[[[2],0],[2,[6,1],6,5],[0,[],[[9],[],[],[10,8,6]],[[9,6,8,2,3],8,1,5,1],[[4],2,[]]],[[10,1,0,6,1],6],[4]]
[[1,[[4,10,2],10],[4],6,[[1,0,7],[8,1,9,5,2],6]]]
[[],[9],[[],[[4,4,1,8],3,5]]]
[[[[10,7],6,[]],[[1,3],[8,9,4],8,[],[2,9]],[8,3],10],[7],[8,9,10]]
[[3,[10,[],4],[[8,3],4,6,[0,6,9,3,6],[8,9,5,9]],[10,[7,1,0,1],[7,1,2,1],[],[]]]]
[[7,2]]
[[8,[],2,0],[[1,[10,7],[0],2,0]],[4,0,[10,[0,5,1],[1],[]],6,[9]]]
[[],[6,[[5,1,6,0,5],4],[7,7,[6],8,[2,1]],1,[[3,0]]],[4,10,[[5,10],[4,9,2,1,5],[7,1,5,6]]],[],[1,9,[]]]
[[[[5,7,1,2],[8],[7,0,9,7,3],[4,2,1],1],8,[4,1,[8,6,1,10],[6,8,3,2,0]],[[3],1,[2]]],[[8,[7,10,1,5,2],[1,1],[1,2]],[[0,4],2,1,[4,6,8]],1,0,3],[10,1,[[0,0,7,8,7],3]],[[4,[4],3,7,[]],3,[10,1,5,[9,6,3]],[[3],[2]],[[],1,10,[2,7]]],[[[9],7,3],8,10]]
[[[3]],[[10],2,3]]
[[[10,4],1,[[4,2,5,8],3,6,[6,10,5,5],5],6],[[7,3,4,5],3,[],[]]]
[[[[0,5,8,4],[2,3,9,1],5],[[9,7,1,5,3],6,[4],[9,2]],[]],[10,[4,1,3,2,7]],[2,9,[4,[],8,[8,10,6,10,10]],[5,8,[]]],[10,4,3,3],[]]
[[],[[[0,9,10,9],9]],[3,[[],[10],4,[4,2,7,8]],0,[[9,10,1,2],9,0],[5]]]
[[[[8,2,9,9],9,4,2],[[9,9],0],[9,[4,1],2,[2,5],2]],[]]
[[],[[0,[4,9]],[4,7,[9],7],[[1,8,9,7,5],[1,4],3,[9,1],4],[4,10,[1],[],[]]],[[5,4,2,10,[9,7,0,4]]],[[[0,10],4],1,5,[[10,7,0,8,9],[6,10,6]],1],[[[5,7],7,5,[]],10,[[6,10,1],[0,8,0]],[],6]]
[[7,[[0,5,8,1],[10,10,0,2],[3]],10],[[[0,1,2,7],4],[1,6]],[[[3],[2],[]],6],[[1],[]]]
[[2],[[],2],[3,9],[],[7,[],1,[[4],8,6,[9,4]],9]]
[[7,[[],[2,10,5,10],1,0,[9,2,1]]],[8,[[],0],4,9],[4,[6,3,5],7]]
[[[[5,5,6,3],[2],8,[]],[[10,1,4,7]],8,6],[[9]]]
[[[[8,9],4]],[[[6,0,6],[0,4,2,8,5],2,[5,6,0,9],1],10,4],[]]
[[[[0],10],[[6,2,10,8]]],[],[[[2],10,3],[],2,10,[10,[]]]]
[[[],1,[]],[[],8]]
[[[2,[10,8,8],[7,1,7,1]],7,1,[]],[6,[[5,10,5,6],2],2,[2,2,[6],10,8]],[[[5,1],[7],1],2,2,10]]
[[5,[3,[8,2,10],[3,10,10,10]],2,7]]
[[],[9,1,4,[1]],[10,[[8,9,2,1],8,6,[],6],8,5],[]]
[[[8,5],[[],2,7,[5,0],[10,5,6,8]]]]
[[[]],[[1,1,5,10,[4,0,10,6,1]],[10,[2,4,7,7],[6,0,8,7]],9,0]]
[[[[4,9,6,4,9],2,[5,1,0,1,5]]],[[1,[4,7,5],8,5],[7,[9,4,8,3,7],8,8,[6,8,3,10,2]],[[6],[8],[2,5,8,3],0]],[]]
[[[4,6,[8,2,10],9],[6],5],[[],0,[1,[4,5,9,1],2]]]
[[[],9,[8,6,[4]]]]
[[6,[]],[4,[],[3,[6,8],[1,6,7,6,6]],6],[],[2,5,5]]
[[8,[[5,3],2,2,6,6]],[]]
[[2,[]],[],[[3,9,10],9]]
[[[]]]
[[[9,[8,6,1,5,0],7,[5,0],[5]],[[]]]]
[[7,4,[[6,4,6,5]],[[9,1],[3,0]],4],[0,[[10,4,8]]],[],[],[[6,7],0,[],[]]]
[[9,3,[8],[10,[10],[7,4]]],[1,[[10,9,4],[7,6],[]],10,5,[]],[[5,7,0],[[3,6,2,8,7]],[[2,6],[],[1,3,9,8,8],10,5],6],[10],[[0,3,7],[[7,1,1,2,1],9]]]
[[1,[3,[],[5,3,9,2],[10,5,4,1,7],[1,5,7]]],[[4,[4,0],9,0]],[[1,[9,8,0,6,9]],2,[[7],7,[1],[10]],7],[[0,[],[6],[]]]]
[[6,1,[10,[4,1,3],1,9]],[]]
[[],[],[],[10]]
[[8,[[10],0,1]]]
[[7,2,7,8],[],[6,0,6,4],[[[5,4,5],7],6,[],[]]]
[[],[[[8,2],7,9],4,2],[7,0],[]]
[[0,1,9,7,5],[[[4,1,10]],8,6],[[[8,9,9,10],[6,5],[8,5,3,5]]],[[],8]]
[[[4,5,6,8],[[5,0,7,10,8],0,[],[7,4,9,9,3]],[]],[],[0,5,[6,8]],[4,[2,[0],[10,1,9,7]],8,3],[]]
[[],[]]
[[[4],4,9],[],[[[3,1],[4,2,5,10,1]],3,[[5,1,0,1,2]],10,[7,[10,5,9,9,9],[2,3,4,10],[2,1],9]]]
[[6,[10,[10]],[7,[4,0,4]],[[0,3,10],7]],[[[9,7,2],7,9,[7,4,8,4,9]],2]]
[[7],[[3,[],[5],[0,6]],[[3,10,5]]]]
[[3,[4,7,[9,0,1,1,7]],0],[[8]]]
[[9,4]]
[[9,[[5],2]],[3,3,[4,[9,3,8],0,5],3,7],[9,5,6],[10,9,2,5,1]]
[[[],[6],8],[[[8],9,[5],1],[6],4,6],[[[]],6],[],[5,[8,8,[10],[5,1,5,9],4],[5,7]]]
[[6,[[],2,9,3],7],[4,[[5,9],3,[3,5,5]],7,7],[[],[[2,0,2,9,3],6],[],[[9,6]],2],[5,9,[[],2,[9,10,10],[7,0,4,1],9],9,[[8,2,2]]]]
[[[7,5,[5,10,1,9],[2,9,9,3]],1,[6,9,[7,9,6]],9,[[5,1,9,10,0]]],[6,8,[]],[],[[2,[2,5,4,9,10],[3,3,3],1],7,[2,9],[4,7,7,[5],[1,2,5,9,8]]],[4,[[],[7]],8,2,1]]
[[4,9,3],[6,[],[6,[7,7,9,1,5],[10,4],10],10,3]]
[[[2,3,[7,5,1,0],5,[10,2,0]]],[7,6],[[[1,0,8,10,2],1]],[0],[6]]
[[10,6],[7,10],[[4],[]],[8,[],[[],10,2,10],[[9,3],[6,9,8],[10,2,4,1],8],2]]
[[[],4],[10,8,[3,9,[]],9],[8,5,[],2],[[8,[10,5,7,2,10],[4,10,7,9],[4,4,5]],[[5,4,6]],[],4]]
[[],[0,8,[5,[6,3,0,7],1,9,6],[3,8,[10,3,8,10],4],[8,[10,6,10],10,[],4]]]
[[[[],6,[5,5],8,[0,5,1]],[7,4,4,[4,1,3,0],8],3,[5,6],8],[9,[4]],[[0,[6,5],1],2,[],[],[2,[8,0,2,10,6],1,[5,8,9,9,4]]],[9,9,[],0]]
[[2,[[7,9,8,8,10],[],[4,5]],[[1,10],7,[1,9,1,0]]],[[4,[6,10,1,5],5,6],[],[[4,9,2,3,2],6,[3,0,2,2]],9,[]],[5,[[10,0,10,6,4],1]],[9,[0,[8,2,2],8,[5],4],[]]]
[[[8],[7,6,10]],[2,5,[[9,9,1,2],[],[],2,4],1],[],[[[7,3,8],1,1,0],[[4,8,7,10,3]],6]]
[[],[[9,9,[4,2]],[7,[],9,[3]],[[1,5,0],[9,3,6,1,2]],[[9,9],4,10,1],1]]
[[],[[0,[9,6],[2,4],9,3],[]],[5],[],[6,[[4,1,0,7,7],[]]]]
[[8,10,6,[],4],[[9,7,2,8]],[0,[5,10,[3],[6,5,9],[4,4]],[],6],[[[],2],8,[9,[3],5,[10,1],8],0],[[3]]]
[[[4,5,[],6,[]],[0,6,[2,4]],10],[[1,[10,6,4,10],[10,4]],1,7,10,7],[],[[],[4,10,[9,0]]],[[6,[10,7,0,7,10]]]]
[[3,[3,[4,1,1,10,10],[8,4]],4],[]]
[[10,[10,4,7]],[7,[1,2,[0,8,6,7]]],[4,6,4]]
[[10,10],[[[2,4,4],0],4]]
[[[[10,4],[1,4,7,1]],2],[[[]]],[3]]
[[[[],[5,4,5,9],8,5],[[],0,4,[1,0],6]],[[3],[[],6,7,0,[7,1]],8,7,8]]
[[[[6,6,5,8],[10,2],[4,10,0]]],[[[1],[4],[0,3,5],[0,1]],[6,[0]],8,1],[1,10,8]]
[[[10,3],[6,[2,2],5]],[[10],[],[[7]],[[],3,[0,0,1,8,0],3,[]],2],[],[]]
[[6],[[],7,[[1,2,0,1]]],[[7]]]
[[[[],[],3]],[]]
[[1,[[5,2,1,10]]]]
[[],[6,1,[]],[1,10,5,6,[[1],[10],2,[2],[4,6,10]]],[]]
[[10,[2,[6,9,4,10,7],[5,8],0],8,10,6],[[[4,10,1]],[[7],[7,4,10,0],[7]],10],[],[[2,[0,2,10,10,1],7,8],[9],[1,[0],[2]],[8,7,[]]],[[]]]
[[1,2,3,[3],[]]]
[[[],1,10,3],[],[5,2,0]]
[[10],[5,1,[8,[9,0,9,10]]],[],[[0],[10,10],4,1]]
[[0,[[0,5],5,2,3]]]
[[],[[],5],[],[0]]
[[3,[9,1,3,[0,9,1,4]]],[],[3,6,[3,10,6]]]
[[9,[[],[7,6],[9],1,10],7,[[4,0],[7],[1]],[1,1,3,[4,5,3,10],1]],[7,4,[[2,9,1,9,3],5,[4]],[8],8]]
[[[[4,5,7],[0],6,[6,7]],8,4]]
[[4,3,[[7,4,6],0,2]],[3,3,8,[[5,5,1,8],[8,2,3],7,3,10],7]]
[[[[7],3,7],0,7,2],[7,[[4,6,8,2,4]],[[6,6,5],[4,4,5,6,6]],[],5],[10,9],[]]
[[2,[[6,2,7,5,7],5,1,3],8],[5,[8,[5,9,8],[],[7,5,3],[4,9,0,2]]]]
[[[2]],[3,[0]],[9,10,2,[],[[7,0,8],4]]]
[[[6,[],7],6,5,9,7],[9,[5,[10,1]],[6],3],[0],[4,4,9,7,[3,6,3,8]]]
[[6,0]]
[[4],[[[4,6],[4,10,3],2,[]],3]]
[[6,8],[[],[5,8,7,3,[]],2,[5,10,[0,5]]],[10,[3,7,[0,5,6,3],1,[9,4,5,1]],5],[[],[7,0,0],[7,6],[7,[7,3,1,1,1],0],[[],8,[]]]]
[]
[[[1,[6]]]]
[[[8,[],[6,9,0,9,7],3,0],4,5,5,[[],8]],[0,5,7,[10,9,[]]],[],[[],[10],[5,8,7]],[6,[[6,10,1],0,[4,9,8,4,7],6,[0,4,9,2]],[5,[1,5,7,1]],3]]
[[10,[0,1,[10],[]],[]],[[8,6],4,9,8,0],[5,[[3,0,6,7],1],4,8],[5,[8,[3]],9,3,[[10,5]]]]
[[[[1,10],[5],[6,2,2],5],[8,5,8,[6,0,0],3]],[]]
[[1,[9,[3,6,3,9]],[[10,4,2],4,4],[[5,10,4]]],[2,[[10],3],[6,[],[2,10],1,[2,4,6,8]],[8,[8,8,9,2],[],7,[2]],[[10,5,5,10],[3,0,10,2,6],[2,2,7,8]]],[[[6,7,1],[8,7],[4,4,4,4],[],9],3,9,0],[[4,2,[2,3],0],[[10],8,1,5]]]
[[[],[10,[2,10,8]]],[]]
[[2,9,4,2,[[2,6,4,9],[10,4,4],[],0,[]]],[[[9,0,9,5],[0,1,0,6,10],[10,2,0,6],10]]]
[[[],7,[3,9,[],2,[2]],10],[],[7,1,[[4,1],[],[5,3,1,8,2]],4,4]]
[[10,[[6],[10,8,1,5],[2,3],3],[[6],8],[5,[4,6],[5,2]],[[8,8,2]]],[2],[[[],[5,3,7],5,[8,2,6]]],[[[2]]]]
[[10,8,9,4,[8,[],8]],[5,7],[]]
[[5],[],[[[1,8,0,8],[1,7,4],5,[]],[],[[]],[2,8,[6],10,10]],[[[0],9,[],[1,0]],10,7,3]]
[[3,[],5,[[10],[9],5],[[10,3,6,9],[8,7],2]],[8,9],[7,[]],[[5],[],8,0]]
[[10,[[9,2,3,7],10,[3,8,4,3]],[10,[3],[4,4]],[2]],[],[3,[7,[9,8,10,10,1],10,[10],1],[7,8,6,[4,8,7],2],6],[[[10]],[[10,7,1],2],0,[[]],8],[]]
[[3,0,1,[7,[0,7,5,2],[],[],[6,5,0]]],[],[],[10],[9,5,[]]]
[[0,8,[],[[1,0],[5,8,3]],[9,8,10]]]
[[],[8,[]]]
[[[7,9],[]],[],[[[1,10,3,8,4]],[9]],[]]
[[[],6,[4,1],2],[9,10],[6,0,1,3],[3,[],[],[7,2]]]
[[[10,[],8,9,[0,1,7,3]],[[10,4,10]]],[],[[5,[5,7,6,7],5,4],3,8,[6,[],[3,2,10],[5,6,2,7]],8],[7,[[9,7,2],8,3,0,9],[5,4,4],7]]
[[[]],[],[2,[],0],[[2,[],4,4]],[[10,[4,7],[1,3,2,4,2]],[],[6,[8,1,3,2],2],6,[5,10,[8,10,6,8,2],6,[]]]]
[[[[7,6,1,3],8,[]],3,1,[0,[5,0,9,8],4,9]],[[[3,10,5,8],[2,2,4],[9,7,6],[7,7,10],0],5,[[0],[4,9,3],3,1,1],[[9],6,5],[]]]
[[3,1,[6,[9,0,3],[2,9,1,2,7],2,[9,9,5]],[0,0,0],3],[8,4,[[2,10,9,6,2],0,[7,5]],[7,2,[9]]]]
[[[10,[],[1,9,4],[0,7,10]],10,10,[[],[7,1,1,9],[4,5,7,2,0],9]],[[[8,7,7,7,10],2,9],[],[[4,10,6,6],[]]],[]]
[[[[],8,[6,0,1],9,9],3],[],[]]
[8,3,10,5]
[8,3,10,5,4]
[[[10,8,1,6],9],[4],[[8],10,[[1,3,2,10],[1,1,8,8,4],10,6]],[9,2],[[[8,9],5,9]]]
[[[[1,5,1,8],[3,6],5],7,10,7,4],[[9,4,6,5,9],[[0],3,[2,2,10,1,1],1],[2,2,[2,10,7],5,10]],[7,6,[4],[[],3,10]]]
[[4,[],[9],7],[5],[[7]],[8,[[3,9,10],10,[4,4,1,7],[7,1,0]],[[2,3,1,7,10],1],5],[9,10,9,[]]]
[[1,1,8,1],[]]
[[[[0,9,3,8],9]],[7,[[8,7,6],4,1,5,[10]],2,[5,[9,6,4,9],[6,7,5,8],10]],[[5,4],8,1,8],[]]
[[7,10,10,[[2,6,6],2],[[]]],[],[5,7,[1,[]],[[4,8,7]],1]]
[[9],[2],[],[]]
[[[],[0,1,4,4],[],[[10,8,8,4],9,[0,2,4,6],[],[7,2,8,9]]],[6,[[2,5,5,8],6,1,[7,1,7,2],[6,9]],[[4,5,6],5,4]],[[]],[],[4,4,[[9],[],9,0,2]]]
[[],[[0,[10,3,3],4,5],[6,9,4]]]
[[9,[[],2,[1],[4,4,6]],[[9],[6,5,2],[6,3,7,4],4],[]],[2],[],[[[2,7],[1,1,10,2,9],7]],[[],[[10,6,4,3],[]],0,[4],[[4],1,10,5]]]
[[[[3],5],[7,9,10]],[2,[1,7,8,[3]],[]],[]]
[[7,6,[],0],[],[[[7,6],[10],1,2,10],1,1,[6,10],[[4,10,4]]],[0,[],[],8,[[5,6,0,1,0]]],[6]]
[[3,[9],[2,[5,0,5,8],[],4],[9,[8],[2,5,4]],[2,[4,7,2],[10,0,3,8,8]]],[[10,2],7,3,9,[[4],1,[1,9,6,9],10,10]],[1],[4,4],[[[7,1],1],10]]
[[[[4,2,1,3],7,[6,0,9,6,8],[3,0,10],8],6,[],3],[[[6],[0,10,5,4,6],7],10,[9,7,[10,3,0,4,0],2,[9,4,2,5]]],[3,[0],[[9,0,1,6,1]]],[[4,1,8,8],[[5,0,6,3,8],[7,8,7],7,[10,6,5]],5,[0],[[],9,9]],[[5]]]
[[[6,[0],[0]],9,[10,7,[10,1,6,8],10],[[],3,2,9],3],[7]]
[[[[9],[8,5,4,6]],10,[[9,6],4,5],6,4],[[10,[]],10,2],[],[[[8,10,9],7,0],[[4],[5,9,8,1,2]],[[8],[10,9,3],[2,6,3,2,6],1],[[6,8],[5,5,4],3]],[[8,1],[5,10],6,0,1]]
[[8,[0,1,6,6,8]],[],[[1,9,2,[4,5,2,4]],4,[],[7,1,7],7]]
[[[7,[7,1],4,10],5,5],[[[1,6,8,9,2],[4],[5,5,7]],1,10,[0,[10,6],3]],[],[[[6],[6,2,0,10]],[[6,6,4,1,3],1],[]],[1,[[7,2],5],[],[2,8,10,[10,1,2,2],4]]]
[2,0,1,0,6]
[2,0,1,0]
[[],[5,[],3,[[1,9,3]],2],[[[],[3,2,3,2,7],[1,10,6,3,9]],1,8]]
[[6],[[[1,0,6],[6,4]],7,1,[2,[5]],7]]
[[9,0,4]]
[[1,10,5,9,[5,5]],[[[3,8,10,8],0,[4],[8],[9,7]]],[[[1,5,4],10],9],[4,[[5,2,8,8],[10,5]],4]]
[[7,6]]
[[[],[[10],0,8],0],[1,5]]
[[[[2],4,[8,7,7,0,4],[3],7],[],[[3,6,6,1]],6],[[[7,0]],1,[1]],[[0,10,[1,0,5],[0,5]],8,4,[9],[0]],[[3,0]],[9]]
[[],[[[0,6,6]],[[8]],3,[1],9]]
[[[4,[0,2,0],8],[[5,10,6,6],[2]]],[],[]]
[[0,6,4],[8,[5,[]],[[9,3],[9],[2,5,0]]],[[10,8,2,[3,0,4,9]],[6,6,5],[4,[],5,9],9],[[[5,0,10,5],5,3],6,4]]
[[0,4,[],4]]
[[[1,[]],6,9,[[4,0],[]]]]
[[0,[[1],10,[4,7],4]],[[10],1,[3],6],[[[7,2,0,7,0],9,[0,8,4],1,6],[[9,2,0]],8,6,[10,8]],[[],10,[9,[8,5,0]],[10],3],[]]
[[1,[[],9,[7],[7,6]],[3,5,1]]]
[[6],[1,6,[[2,3,2],[7,9,4,3,5],5,[6,6]],[9,5,2,0],[3,[7,1,4,1,2],4,[2,7,7,9],[8,8,4,10]]],[]]
[[[10,7,[],[3,4],[8,1]],[5,[9],3]],[[3,[8,7,0,8,6],[0],[5,3,1,0,5]],[9,[4],10,[8,0,2,10],2]],[[[10,10],0],[]]]
[[2,[[7,5,10,9]],5,5,[]],[[[1,6,5,10,6],[5,8,4,10],[2,5,3,8]]],[[],[[2,10,1],[],8],5],[]]
[[3,[10],9,[5,[],[2,3],6,7]],[[],4,9],[],[[[1,10,4,10]],0,10]]
[[],[10,[2,[0,8],[7,4],6],2,2,[[2,2,7,2,9]]],[0,[]]]
[[[[10]]],[],[],[[[2,2],6,0,[]],[],10,3,[[4,7,1],[6,10],2]]]
[[[4],[],5]]
[[],[[],3,8,8,10],[7]]
[[]]
[[[3,5,1,[0,8,0,7,6]],[2,10,1,[]],[[8,8,3,8,2]],[[10,1],1,[0,2,6],[10]]],[[[1,2],[5,2,6,7,9],10,1],2,5,[]],[[7],[6,9,10],[2,[6,4,10,1]],3,[[10,5,8],9,[2,5,10,2]]],[[5,6,[7,7,8]],[7,[],7],[],[6,10,[7,7,5]]],[]]
[[[5,[5],[],10,[3]]],[],[],[5,3,4,8,[[0,10,7,3],[5,5,6],[10,7,9,2,7],[6]]],[[],[[6,0,5,10]],[[10,1,1,5,7],[8,6],[],[5,5,5],2]]]
[[8,[9,4,[8,0,3],[0,4],2],[[3],1,1,4]],[5,[1,[],6,5,[4,7,0,8]],3,[[3,8,10,0]]],[7,4,[],1,6],[[[7,4,9,10,8],[],10,[7,9],[2,1,3,8]],2],[[[8,5,1,6,6],[3,9,3,1],[2,10,0,3,5]],7]]
[[7],[2,[10,[9],[9,10],[1,5,8,8,3]],[[3,7,0],3,[9,1,0,9,10],8,[5]],[[1,6,10,9]],3],[[9,1],[[10,1,7]],6]]
[[9,[],4,[[],5],5],[8,[5,6,3,[5,8],[4,10,0]],[3,8]],[8,[[0,1],3,0,1],4,[[2,9,3,1]]],[[5,3,5,1,[6,5,6,3,6]]],[1,[[]],[5],[2],7]]
[[10,9,9,2],[[10,6,7,6,[0,1,10,10,0]]],[2,[3,[6,9,5],9,[]]],[8,2,[]]]
[[],[[7,[8,10,7],[7,8,10,6],3,[]]],[],[[[5,5,1,4,2],6],[],0],[2,4]]
[[5,[8,0,[7,10,7],9,[1,6,9,2]],7],[[10,9,[7]],2,[4,[10,7,0,8,6],[],[4,1],5]],[]]
[[6,2],[0,[],6,[[1,10,4,8,8]]]]
[[[5,[]]]]
[[6,[],2],[0],[[],10,[[1,8],4,[9],[5,2,0,6,9]],[]]]
[[10,[[],[5,8,10]],2,[10,1],[]],[[],5,[6],[3,[2,0,4],6,4,3],[7,4,[],1,7]]]
[[[[5,0],[10,10,3],[9,10,10,10,5],5],5,[[0,1,10,9],10,[8,8,6]],5,9]]
[[4,[[]],[]],[],[[10,[7],0,[3,10,1]]],[[6,3],10,10,[2]],[3,4,[3,6,10,0],[[5],8,[3],[6,2,8,2,2]]]]
[[2,[0,[3]]],[9]]
[[[2,5,[9,10,7],[0]],[[4]]],[9,3,[3,10,9],[9,[3,9,10],[6,3,10]]]]
[[],[8],[[[],10,[],8],5,4],[[6,10,[],5],[8]],[[8,[9,10]],[[9,0,3,4,10],[7,9,4],8]]]
[[5,7,5],[1],[1,[],10],[[9],5,10,0,[]]]
[[7,0],[[],9,4]]
[[3,[]],[[]],[[0,[7],[8,2,9,0]],[[3,2],[3],[3,3,3]],[]]]
[[[[],5],7,[[0,0,1]]],[9,[6,[10,8],[6,7],1],0,[6,0],0],[2,5,[9,3,6],[[5],8,2,5]],[[[],4],[]]]
[[9,10,2,[5,[],[3,7,0,8,3]]],[[9],4],[2,[[3],[9,2,0,3,8],[9,4,2,9,10]],[[5],[4,2,0,8],9,[],[1,6,6,7,8]],10,8],[9,2]]
[[0],[10,[[2],3,2,[9]],[0]],[9,[8]],[1,[],[2,2],8],[7,6,[8,[],5,8],[[6]],7]]
[[0],[[5,7,3,8],[[1,5,2,2,5],9,3],[],[],[[0,0,5,6,1],9]],[[9]]]
[[3,[[3,6,8,3],[]],4],[[9]],[1,[0]]]
[[[1,[6,3,1,4,4],[]],10,10],[[[],[4,6,2,8],[7,3,8]],[],[8],[[9],[4],[5,8]]]]
[[8]]
[[],[8,[[0,2,0],[4],2],[8,[]],10,[]],[0],[[7,2,[6,4,10,7,8],[8,2,10],[3,10,9,5]],[],[1],3]]
[[8,3],[[[7,2],[4]],[],[7,10,[7,7,4],[0,5]]],[10,6,8,8,[[10,9],[9,7],[0,10],[10,6,5,6,2]]],[10,7,8,[[7],3,6]]]
[[[10,[7,6,5,8,7],10,4]]]
[[[9,2,7,2],[[8]]]]
[[],[[0,[8,5,1],2],[[5,9,4,1],8,2],[[3,6,1],[5,4,4,7],[6]]],[],[4,8,[[5,9,6,4],9,[10,6],[0,8,9,1,10]],[4],2]]
[[6,2,[[7,10,2,8,5],2]]]
[[3,[],0,[]],[2,8,[[5]],[2,6,[0,7,0,1]]]]
[[2,[[3,4,9,9],[],[6,6,5,3],9],0],[],[9],[[],[8,2,2,[9,6,0,5],[0]],5,6]]
[[[],8,5],[10,[[8],6]]]
[[[8,5],2,5],[],[]]
[[10,10,[0,0,[4,1,10,5,6]],0,[[7,2],5]],[],[[[10,9],[1,2],[8,1]],6,2,10],[[[10,7],8,[1,9,6,6,10],5,5]]]
[[[[10,10,2],[6,6,6]],[5,5,[4,8,10,5,9]],5,[],[[2,6],4,7,[8,5,6],[2,3,9,2,1]]],[[5],7],[1,[2,3,[1,6,8,8,4]],9]]
[[9],[3],[2,[[],7,4,4,[7,2]],[1,[4,5,6,3]],5,[[7],9,9]]]
[[6],[[5,[8,7]],[[4,4,8,2],9]],[1,7,4,[[5],4,[2],10],10],[6,10,10,[]]]
[[10,4,[[5,0],[2,0,2,4,7],[8,3,7,1],8],[],6],[[4,[10,9]],1,10],[[[1,5,6,2,7],3],[[7,0,2,3],1],[[]]],[[5,[2,1,8],[2,3,9]],[[9,1],[3,3,1,2],[10,6,3,5,2]]],[]]
[[[1,6],[6,2,[3,8,10],[],[7]]],[],[8,[9,[9,1,2,4,10]],8,[],0],[]]
[[[[0],[0,10,7,8],10,9],3]]
[[8,1],[[[2,8,1,1],[],0]],[[],10,3,7]]
[[[1]],[[5,[3,3,0,8],[8,8,5,5,8],7,6],[6,[2,10,3,9],[4],[5,6,1,8,7],[0,9]],[[0,2,2],1,1,5,8],10],[2,3,[6,[9,9,8,1],[],2],7,5],[0,0,1,[],[9]]]
[[9,5],[8,[[10]]],[[[7]],8,2],[3,4],[9,[],[[4,4],3,[3],[9],[5]],[2,[7,3],[0,0],[10,8,2]],10]]
[[[[3,1,7,9],2,[0,0,1,4]],8],[[[7,4],9],[7,9,[],2,10],10],[[[0,2,2],4,6,3,6],2,4],[[8,[4,1,9,3],8,7],[[1],[1,0,6],9,9,5],4],[]]
[[7,2,[[6,5],[6,1],[3,5,5,3,3],9],[[0,7,2],[5,0,2,10,4],[8,3],[],10],0],[]]
[[2,9,1,10]]
[[],[9,10],[8,[[10,10,7,0],[10,2,1,9,3],1,[6,8,8]]],[],[[[10,2]],[[6,0,9,6,4],7],7]]
[[5,4,8,4]]
[[],[[6]],[[8,2,0,[]],[],2],[6,1,[10,2,5],[[],[10],[8,0]]],[[6,2],7,[8,[1]],[]]]
[[[5,6,[1,8],10],[9,[2,3,5,6,10],0,[4,3,5]],2],[],[1,9,1,9,[[],[1],4,10,[2,1,9,5,5]]],[3,2,[],6],[[],[],3,6,2]]
[[1,[[3],10,2,6]],[],[[10,7],2,[],[[],5,6,[2,10]]],[[[9,2],9],[[],4,[10,4,3],10,1],[[4,1,10],[0,3],7],[2,5,7,[0,9,8,5]]]]
[[[],8,[],3],[8,[4,[3,0],[6,6],7,[0,3,5,6]],10,[[10,8,1,1,1]],[]],[4],[4,7],[10,[],1,[9,[0,2],4,2,2],[[5],[1,2,3,7],0,7]]]
[[[10,4,[10,2]]],[[[7,5,8],4,[2,1]],4,9]]
[[0],[],[2,[[1,6,3,5,4],7],4,9]]
[[[2,[6,10,2,10],1,8,[]],10,[7,[],2],[[],5,1,[],4],1],[3,[[10,5,7],[1,5,8,3,9],[7,10,0,5,8]],[[0,4,7,2,1],[6,2,1],[3],0]],[0,2,3]]
[[9,10,3],[[3,[2,8,3],6,2,8],[0,[7]],0],[1,8,[[5,2]],[[7,6,6,5]]]]
[[[]],[10,10,9],[[[2],8],10,[]],[[],[7,[7,9,0],[],0],[2]],[[],[[10],[9,9,2,1,4]],7,4]]
[[2,4],[[1,7,3,5],8]]
[[],[5],[5,9],[2,3,[8,3,[0],2,6]]]
[[[[0,3],[9,2,5,9,4],[5,2,9,8],[5],9],[9,7,[2,4,8]],8,3,[[6],[2]]]]
[[7],[[],10,1,[[8,5,8],[8],[5],[1,2],6]],[9,[[2,2],10,[],4],[],[[3],9,[0,10,8,9]],5]]
[[[[]]],[8,6],[[]],[],[[6,2,5]]]
[[[2,10,[7,6,2]],[10,2],0,10],[[0,6],1,5,7],[10,[]]]
[[],[7,1,[]],[9,3,9],[6],[0,4]]
[[],[[[4,1,3],[10,9,8,7,9],7,[1,2],[8,0,2,5]],[6],6],[]]
[[],[[],[8],[[0,4],8,[7,8,3,9,9]],[],[[],[6,6,10],0]],[[1,1,[],[10,2,8,7]],[[9,6],[9,6,2,10],2,10,10]],[[8,[5,5,7]],[3,8],3],[[[6,0,2,2],[],8],[0,[7,5,4],4,[4],[1]],[8,6],5,3]]
[[[10,3],[[1,0,7,3],6,[1,1,2,10],5,[6,7,4]],[],[5]],[],[],[3,4,[[3,7,9,3,0],6,4]],[0,3,0]]
[[],[],[4,[10,7,[2,9,5]],[],[9,1],10]]
[[[],[2,[1,9],[]]],[],[],[],[6,9,[[6,8],5,2,[4,3,4,6,6]],[[5,2,3,8]],[[3,8],4,5,[4,2,4,1]]]]
[[7,[5,[4],4],1,[[2,5,8,2],0,[9,4]],1],[[9,4,8,[0],5]],[],[8,[5,[2,5,8,6,8],3,1]],[]]
[[[0,[9,6,2,7,9]],[8,[1,1,8]],4,[3],8],[[5,[8,6],3,1,5],4,8,[],[[1,1]]]]
[[],[[3,3],[[8,8],10,2],9,4],[0],[3]]
[[3],[],[8],[]]
[[[5,[8,5]],[9,2]],[[[4,9],[3,1],[2,7,5],[2,9,2]],0],[[2,10,2,[],[4,4,4]]],[[7,[1,2,5],[],9],[8,3,[3,8,0,1,10],0,5],1,7],[[[8,0,6,2],[],4,[10]],3,[],4,8]]
[[[[9,8,4,2,4],[0,2,0],5],[7,[4,7,10],[]],[[4,0],2],[8,[2,0,10,4],[7,6]]],[],[1,[[1,4,9,8,6],4]]]
""";
#endregion
}

582
Days/Day14.cs Normal file
View File

@@ -0,0 +1,582 @@
using System.Drawing;
using Spectre.Console;
using Color = Spectre.Console.Color;
namespace AdventOfCode.Days;
public enum CellType
{
Air = 0,
Rock,
Sand
}
public class MapPath
{
public IEnumerable<Point> Points => _points;
private readonly IList<Point> _points;
public MapPath()
{
_points = new List<Point>();
}
public MapPath(IEnumerable<Point> points)
{
_points = new List<Point>(points);
}
public void AddPoint(Point point)
{
_points.Add(point);
}
public void DrawPath(CellType[,] map, int xOffset, int yOffset)
{
if (!_points.Any())
{
return;
}
// Draw each point
var previousPoint = _points.First();
foreach (var point in _points.Skip(1))
{
// Draw horizontally
if (previousPoint.X != point.X)
{
var xStart = Math.Min(previousPoint.X, point.X);
var xEnd = Math.Max(previousPoint.X, point.X);
for (int x = xStart; x <= xEnd; x++)
{
map[x + xOffset, point.Y + yOffset] = CellType.Rock;
}
}
// Draw vertically
else
{
var yStart = Math.Min(previousPoint.Y, point.Y);
var yEnd = Math.Max(previousPoint.Y, point.Y);
for (int y = yStart; y <= yEnd; y++)
{
map[point.X + xOffset, y + yOffset] = CellType.Rock;
}
}
// Use current point for next point drawing
previousPoint = point;
}
}
public void DrawPath(IDictionary<Point, CellType> map)
{
if (!_points.Any())
{
return;
}
// Draw each point
var previousPoint = _points.First();
foreach (var point in _points.Skip(1))
{
// Draw horizontally
if (previousPoint.X != point.X)
{
var xStart = Math.Min(previousPoint.X, point.X);
var xEnd = Math.Max(previousPoint.X, point.X);
for (int x = xStart; x <= xEnd; x++)
{
map[point with { X = x }] = CellType.Rock;
}
}
// Draw vertically
else
{
var yStart = Math.Min(previousPoint.Y, point.Y);
var yEnd = Math.Max(previousPoint.Y, point.Y);
for (int y = yStart; y <= yEnd; y++)
{
map[point with { Y = y }] = CellType.Rock;
}
}
// Use current point for next point drawing
previousPoint = point;
}
}
}
public class Day14 : Day
{
public override int Number => 14;
public override string Name => "Regolith Reservoir";
private readonly Point _sandSource = new(500, 0);
private Point _offsetSandSource;
public override void RunPart1(bool display = true)
{
var map = GenerateMap();
// Draw canvas
var canvas = GenerateCanvas(map);
canvas.SetPixel(_offsetSandSource.X, _offsetSandSource.Y, Color.IndianRed1);
// Simulate sand fall
int sandBlocksCount = 0;
while (GenerateSand(map, canvas, _offsetSandSource))
{
sandBlocksCount++;
}
if (display)
{
AnsiConsole.Write(canvas);
AnsiConsole.MarkupLine($"[green]Total sand blocks: [yellow]{sandBlocksCount}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var map = GenerateDictionaryMap();
// Compute ground level
var yMax = map.Keys.Max(p => p.Y);
var groundLevel = yMax + 2;
// Simulate sand fall
int sandBlocksCount = 0;
while (GenerateSand(map, _sandSource, groundLevel))
{
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)
{
// Stop if source is blocked
if (map[sandSource.X, sandSource.Y] == CellType.Sand)
{
return false;
}
var width = map.GetLength(0);
var height = map.GetLength(1);
var sandPosition = new Point(sandSource.X, sandSource.Y);
// Make sand fall till we don't go outbound
while (sandPosition.X >= 0 && sandPosition.X < width && sandPosition.Y >= 0 && sandPosition.Y < height)
{
// Fall outbound below
if (sandPosition.Y + 1 >= height)
{
return false;
}
// Try below
if (map[sandPosition.X, sandPosition.Y + 1] == CellType.Air)
{
sandPosition.Y += 1;
continue;
}
// Fall outbound on the left
if (sandPosition.X - 1 < 0)
{
return false;
}
// Try on the left
if (map[sandPosition.X - 1, sandPosition.Y + 1] == CellType.Air)
{
sandPosition.X -= 1;
sandPosition.Y += 1;
continue;
}
// Fall outbound on the right
if (sandPosition.X + 1 >= width)
{
return false;
}
// Lastly try on the right
if (map[sandPosition.X + 1, sandPosition.Y + 1] == CellType.Air)
{
sandPosition.X += 1;
sandPosition.Y += 1;
continue;
}
// Can't go anywhere, stop
break;
}
map[sandPosition.X, sandPosition.Y] = CellType.Sand;
canvas.SetPixel(sandPosition.X, sandPosition.Y, Color.SandyBrown);
return true;
}
private static bool GenerateSand(IDictionary<Point, CellType> map, in Point sandSource, int groundY)
{
// Stop if source is blocked
if (map.GetValueOrDefault(sandSource, CellType.Air) == CellType.Sand)
{
return false;
}
var sandPosition = new Point(sandSource.X, sandSource.Y);
// Make sand fall till we don't go outbound
while (true)
{
// Sand is touching ground, stop here
if (sandPosition.Y + 1 >= groundY)
{
break;
}
// Try below
var below = sandPosition with { Y = sandPosition.Y + 1 };
if (map.GetValueOrDefault(below, CellType.Air) == CellType.Air)
{
sandPosition = below;
continue;
}
// Try on the left
var left = new Point(sandPosition.X - 1, sandPosition.Y + 1);
if (map.GetValueOrDefault(left, CellType.Air) == CellType.Air)
{
sandPosition = left;
continue;
}
// Lastly try on the right
var right = new Point(sandPosition.X + 1, sandPosition.Y + 1);
if (map.GetValueOrDefault(right, CellType.Air) == CellType.Air)
{
sandPosition = right;
continue;
}
// Can't go anywhere, stop
break;
}
map[sandPosition] = CellType.Sand;
return true;
}
private static Canvas GenerateCanvas(CellType[,] map)
{
var width = map.GetLength(0);
var height = map.GetLength(1);
var canvas = new Canvas(width, height);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
canvas.SetPixel(x, y, ColorCellType(map[x, y]));
}
}
return canvas;
}
private static Canvas GenerateCanvas(IDictionary<Point, CellType> map, in Point sandSource)
{
// Compute dimensions
var xMin = map.Keys.Min(p => p.X);
var xMax = map.Keys.Max(p => p.X);
var yMin = map.Keys.Min(p => p.Y);
var yMax = map.Keys.Max(p => p.Y);
var width = xMax - xMin + 1;
var height = yMax - yMin + 1;
var canvas = new Canvas(width, height);
// Fill background
for (int x = xMin; x <= xMax; x++)
{
for (int y = yMin; y <= yMax; y++)
{
canvas.SetPixel(x - xMin, y - yMin, Color.Grey23);
}
}
// Fill canvas
foreach (var (point, cellType) in map)
{
canvas.SetPixel(point.X - xMin, point.Y - yMin, ColorCellType(cellType));
}
canvas.SetPixel(sandSource.X - xMin, sandSource.Y - yMin, Color.IndianRed1);
return canvas;
}
private CellType[,] GenerateMap()
{
var paths = Input.ReadAllLines()
.Select(line => new MapPath(line.Split(" -> ")
.Select(p => p.Split(','))
.Select(s => new Point(int.Parse(s[0]), int.Parse(s[1])))))
.ToList();
// Compute xMin, xMax, yMin, yMax
int xMin = paths.SelectMany(p => p.Points).Min(p => p.X);
int xMax = paths.SelectMany(p => p.Points).Max(p => p.X);
int yMax = paths.SelectMany(p => p.Points).Max(p => p.Y);
// Construct 2D map
var width = xMax - xMin + 1;
var height = yMax + 1;
var map = new CellType[width, height];
// Fill rocks
paths.ForEach(p => p.DrawPath(map, -xMin, 0));
// Compute new sand source
_offsetSandSource = _sandSource;
_offsetSandSource.Offset(-xMin, 0);
return map;
}
private static Color ColorCellType(CellType cellType)
{
return cellType switch
{
CellType.Air => Color.Grey23,
CellType.Rock => Color.LightSlateGrey,
CellType.Sand => Color.SandyBrown,
_ => throw new Exception("Invalid CellType")
};
}
private static IDictionary<Point, CellType> GenerateDictionaryMap()
{
var paths = Input.ReadAllLines()
.Select(line => new MapPath(line.Split(" -> ")
.Select(p => p.Split(','))
.Select(s => new Point(int.Parse(s[0]), int.Parse(s[1])))))
.ToList();
// Construct 2D map
var map = new Dictionary<Point, CellType>();
// Fill rocks
paths.ForEach(p => p.DrawPath(map));
return map;
}
#region Input
public const string Input =
"""
521,171 -> 525,171
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
503,109 -> 507,109
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
488,38 -> 493,38
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
482,93 -> 496,93 -> 496,92
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
497,29 -> 502,29
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
501,32 -> 506,32
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
503,115 -> 507,115
524,173 -> 528,173
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
486,47 -> 490,47
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
495,50 -> 499,50
492,41 -> 496,41
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
522,177 -> 522,178 -> 536,178 -> 536,177
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
503,121 -> 507,121
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
515,121 -> 519,121
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
498,35 -> 503,35
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
503,171 -> 507,171
509,121 -> 513,121
494,12 -> 494,13 -> 507,13 -> 507,12
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
500,112 -> 504,112
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
512,173 -> 516,173
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
502,38 -> 507,38
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
506,169 -> 510,169
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
491,121 -> 495,121
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
518,173 -> 522,173
501,50 -> 505,50
497,115 -> 501,115
498,47 -> 502,47
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
518,169 -> 522,169
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
489,44 -> 493,44
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
509,167 -> 513,167
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
487,133 -> 487,134 -> 501,134
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
512,118 -> 516,118
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
512,165 -> 516,165
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
491,35 -> 496,35
500,173 -> 504,173
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
483,50 -> 487,50
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
500,118 -> 504,118
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
492,47 -> 496,47
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
495,38 -> 500,38
494,12 -> 494,13 -> 507,13 -> 507,12
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
494,118 -> 498,118
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
509,115 -> 513,115
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
506,173 -> 510,173
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
505,35 -> 510,35
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
506,118 -> 510,118
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
503,150 -> 503,154 -> 501,154 -> 501,162 -> 513,162 -> 513,154 -> 507,154 -> 507,150
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
509,171 -> 513,171
494,12 -> 494,13 -> 507,13 -> 507,12
509,38 -> 514,38
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
495,44 -> 499,44
482,93 -> 496,93 -> 496,92
515,171 -> 519,171
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
481,79 -> 481,81 -> 478,81 -> 478,89 -> 490,89 -> 490,81 -> 485,81 -> 485,79
522,177 -> 522,178 -> 536,178 -> 536,177
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
497,147 -> 497,137 -> 497,147 -> 499,147 -> 499,146 -> 499,147 -> 501,147 -> 501,142 -> 501,147 -> 503,147 -> 503,144 -> 503,147 -> 505,147 -> 505,140 -> 505,147
515,167 -> 519,167
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
506,112 -> 510,112
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
522,177 -> 522,178 -> 536,178 -> 536,177
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
488,124 -> 488,126 -> 485,126 -> 485,129 -> 496,129 -> 496,126 -> 491,126 -> 491,124
487,133 -> 487,134 -> 501,134
497,121 -> 501,121
476,63 -> 476,58 -> 476,63 -> 478,63 -> 478,55 -> 478,63 -> 480,63 -> 480,56 -> 480,63 -> 482,63 -> 482,57 -> 482,63 -> 484,63 -> 484,55 -> 484,63 -> 486,63 -> 486,55 -> 486,63
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
489,50 -> 493,50
465,76 -> 465,71 -> 465,76 -> 467,76 -> 467,72 -> 467,76 -> 469,76 -> 469,68 -> 469,76 -> 471,76 -> 471,73 -> 471,76 -> 473,76 -> 473,71 -> 473,76 -> 475,76 -> 475,70 -> 475,76 -> 477,76 -> 477,71 -> 477,76 -> 479,76 -> 479,73 -> 479,76 -> 481,76 -> 481,74 -> 481,76 -> 483,76 -> 483,72 -> 483,76
512,169 -> 516,169
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
494,32 -> 499,32
490,16 -> 490,20 -> 484,20 -> 484,26 -> 499,26 -> 499,20 -> 494,20 -> 494,16
488,106 -> 488,97 -> 488,106 -> 490,106 -> 490,100 -> 490,106 -> 492,106 -> 492,101 -> 492,106 -> 494,106 -> 494,105 -> 494,106 -> 496,106 -> 496,96 -> 496,106 -> 498,106 -> 498,102 -> 498,106 -> 500,106 -> 500,101 -> 500,106 -> 502,106 -> 502,102 -> 502,106 -> 504,106 -> 504,100 -> 504,106
""";
#endregion
}

292
Days/Day15.cs Normal file
View File

@@ -0,0 +1,292 @@
using System.Collections.Concurrent;
using System.Drawing;
using Spectre.Console;
namespace AdventOfCode.Days;
public class SensorBeaconPair
{
public Point SensorPosition { get; }
public Point BeaconPosition { get; }
public int SensorRange =>
Math.Abs(SensorPosition.X - BeaconPosition.X) + Math.Abs(SensorPosition.Y - BeaconPosition.Y);
public SensorBeaconPair(in Point sensorPosition, in Point beaconPosition)
{
SensorPosition = sensorPosition;
BeaconPosition = beaconPosition;
}
}
public class CoverRange
{
public int Start { get; }
public int End { get; }
public int Covered => End - Start + 1;
public CoverRange(int start, int end)
{
Start = start;
End = end;
}
public CoverRange(CoverRange coverRange)
{
Start = coverRange.Start;
End = coverRange.End;
}
public CoverRange Subtract(CoverRange other)
{
// Overlap on left
int newStart;
if (other.Start <= Start && other.End >= Start)
{
newStart = other.End + 1;
}
else
{
newStart = Start;
}
// Overlap on right
int newEnd;
if (other.Start <= End && other.End >= End)
{
newEnd = other.Start - 1;
}
else
{
newEnd = End;
}
return new CoverRange(newStart, newEnd);
}
public static CoverRange operator -(CoverRange left, CoverRange right)
{
return left.Subtract(right);
}
}
public class Day15 : Day
{
public override int Number => 15;
public override string Name => "Beacon Exclusion Zone";
public override void RunPart1(bool display = true)
{
const int targetY = 2_000_000;
// Parse pairs
var pairs = ParsePairs();
var ranges = new List<CoverRange>(pairs.Count);
// Get which columns are included on line targetY, remove the ones which already contains a beacon
var beaconsOnTargetY = new HashSet<int>();
foreach (var sensorBeaconPair in pairs)
{
// Get covered columns on y line
var xCenter = sensorBeaconPair.SensorPosition.X;
var coveredColumns = sensorBeaconPair.SensorRange - Math.Abs(sensorBeaconPair.SensorPosition.Y - targetY);
if (coveredColumns > 0)
{
ranges.Add(new CoverRange(xCenter - coveredColumns, xCenter + coveredColumns));
// Check if the beacon is on targetY
if (sensorBeaconPair.BeaconPosition.Y == targetY)
{
beaconsOnTargetY.Add(sensorBeaconPair.BeaconPosition.X);
}
}
}
// Remove overlapped ranges => inner.Start >= outer.Start && inner.End <= outer.End));
ranges.RemoveAll(inner =>
ranges.Where(outer => outer != inner).Any(outer => inner.Start >= outer.Start && inner.End <= outer.End));
// Compute unique number of x columns
long totalCovered = 0;
for (int i = 0; i < ranges.Count; i++)
{
var range = ranges[i];
var coverRange = range;
// Add number of covered columns and then subtract common ones
for (int j = i + 1; j < ranges.Count; j++)
{
var exclude = ranges[j];
coverRange -= exclude;
}
totalCovered += coverRange.Covered;
}
// Remove lines which contains a beacon
totalCovered -= beaconsOnTargetY.Count;
// Print total covered columns on line Y
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of positions that cannot contain a beacon: [yellow]{totalCovered}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
const int xMin = 0;
const int xMax = 4_000_000;
const int yMin = 0;
const int yMax = 4_000_000;
bool IsOutbound(Point point) => point.X is < xMin or > xMax || point.Y is < yMin or > yMax;
// Parse pairs
var pairs = ParsePairs();
// Find all points that are just outside a sensor range
var possiblePoints = new ConcurrentBag<Point>();
Parallel.For(0, pairs.Count, i =>
{
var pair = pairs[i];
var sensor = pair.SensorPosition;
var distance = pair.SensorRange + 1;
for (int x = -distance; x <= distance; x++)
{
var y = distance - Math.Abs(x);
var positivePoint = new Point(sensor.X + x, sensor.Y + y);
var negativePoint = new Point(sensor.X + x, sensor.Y - y);
// If both points are outbound, just skip
var positiveIsOutbound = IsOutbound(positivePoint);
var negativeIsOutbound = IsOutbound(negativePoint);
if (positiveIsOutbound && negativeIsOutbound)
{
continue;
}
// Check if this point is just outside at least one other sensor range
for (int otherIndex = 0; otherIndex < pairs.Count; otherIndex++)
{
if (otherIndex == i)
{
continue;
}
var otherPair = pairs[otherIndex];
var otherSensor = otherPair.SensorPosition;
var otherDistance = otherPair.SensorRange + 1;
if (!positiveIsOutbound)
{
var distancePositive = Math.Abs(positivePoint.X - otherSensor.X) +
Math.Abs(positivePoint.Y - otherSensor.Y);
if (distancePositive == otherDistance)
{
possiblePoints.Add(positivePoint);
}
}
if (!negativeIsOutbound)
{
var distanceNegative = Math.Abs(negativePoint.X - negativePoint.X) +
Math.Abs(negativePoint.Y - negativePoint.Y);
if (distanceNegative == otherDistance)
{
possiblePoints.Add(negativePoint);
}
}
}
}
});
// Keep the only outside detection point
var finalPoint = possiblePoints.First(f =>
pairs.All(p => Math.Abs(f.X - p.SensorPosition.X) + Math.Abs(f.Y - p.SensorPosition.Y) > p.SensorRange));
var tuningFrequency = finalPoint.X * (long) 4_000_000 + finalPoint.Y;
if (display)
{
AnsiConsole.MarkupLine($"[green]Tuning frequency: [yellow]{tuningFrequency}[/][/]");
}
}
private static IList<SensorBeaconPair> ParsePairs()
{
var pairs = new List<SensorBeaconPair>();
foreach (var line in Input.ReadAllLines())
{
var span = line.AsSpan();
// Parse sensor position
int sensorXStart = span.IndexOf('=') + 1;
int sensorXEnd = span.IndexOf(',');
var sensorX = int.Parse(span[sensorXStart..sensorXEnd]);
span = span[sensorXEnd..];
int sensorYStart = span.IndexOf('=') + 1;
int sensorYEnd = span.IndexOf(':');
var sensorY = int.Parse(span[sensorYStart..sensorYEnd]);
span = span[sensorYEnd..];
// Parse beacon
int beaconXStart = span.IndexOf('=') + 1;
int beaconXEnd = span.IndexOf(',');
var beaconX = int.Parse(span[beaconXStart..beaconXEnd]);
span = span[beaconXEnd..];
int beaconYStart = span.IndexOf('=') + 1;
var beaconY = int.Parse(span[beaconYStart..]);
pairs.Add(new SensorBeaconPair(new Point(sensorX, sensorY), new Point(beaconX, beaconY)));
}
return pairs;
}
#region Input
public const string Input =
"""
Sensor at x=1384790, y=3850432: closest beacon is at x=2674241, y=4192888
Sensor at x=2825953, y=288046: closest beacon is at x=2154954, y=-342775
Sensor at x=3553843, y=2822363: closest beacon is at x=3444765, y=2347460
Sensor at x=2495377, y=3130491: closest beacon is at x=2761496, y=2831113
Sensor at x=1329263, y=1778185: closest beacon is at x=2729595, y=2000000
Sensor at x=2882039, y=2206085: closest beacon is at x=2729595, y=2000000
Sensor at x=3903141, y=2510440: closest beacon is at x=4006219, y=3011198
Sensor at x=3403454, y=3996578: closest beacon is at x=3754119, y=4475047
Sensor at x=3630476, y=1048796: closest beacon is at x=3444765, y=2347460
Sensor at x=16252, y=2089672: closest beacon is at x=-276514, y=2995794
Sensor at x=428672, y=1150723: closest beacon is at x=-281319, y=668868
Sensor at x=2939101, y=3624676: closest beacon is at x=2674241, y=4192888
Sensor at x=3166958, y=2890076: closest beacon is at x=2761496, y=2831113
Sensor at x=3758241, y=3546895: closest beacon is at x=4006219, y=3011198
Sensor at x=218942, y=3011070: closest beacon is at x=-276514, y=2995794
Sensor at x=52656, y=3484635: closest beacon is at x=-276514, y=2995794
Sensor at x=2057106, y=405314: closest beacon is at x=2154954, y=-342775
Sensor at x=1966905, y=2495701: closest beacon is at x=2761496, y=2831113
Sensor at x=511976, y=2696731: closest beacon is at x=-276514, y=2995794
Sensor at x=3094465, y=2478570: closest beacon is at x=3444765, y=2347460
Sensor at x=806671, y=228252: closest beacon is at x=-281319, y=668868
Sensor at x=3011731, y=1976307: closest beacon is at x=2729595, y=2000000
""";
#endregion
}

219
Days/Day16.cs Normal file
View File

@@ -0,0 +1,219 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Valve
{
public string Name { get; }
public int Rate { get; }
public IList<Valve> AccessibleValves { get; }
public Valve(string name, int rate)
{
Name = name;
Rate = rate;
AccessibleValves = new List<Valve>();
}
}
public record ValvePath(int CurrentMinute, int PressurePerMinute, int ReleasedPressure, Valve CurrentValve, HashSet<Valve> OpenedValves);
public class Day16 : Day
{
public override int Number => 16;
public override string Name => "Proboscidea Volcanium";
public override void RunPart1(bool display = true)
{
var startValve = ParseValves();
// Test all possibles paths
int maxPressure = 0;
var paths = new Queue<ValvePath>();
paths.Enqueue(new ValvePath(1, 0, 0, startValve, new HashSet<Valve>()));
// Remember best pressure at each valve
var valvePotential = new Dictionary<Valve, (int currentMinute, int potential)>();
while (paths.Count > 0)
{
var state = paths.Dequeue();
// Check if this state is worse than last one at this same valve
int potential = state.ReleasedPressure + (30 - state.CurrentMinute + 1) * state.PressurePerMinute;
if (valvePotential.TryGetValue(state.CurrentValve, out var lastState))
{
if (state.CurrentMinute >= lastState.currentMinute)
{
if (potential <= lastState.potential)
{
continue;
}
}
}
valvePotential[state.CurrentValve] = (state.CurrentMinute, potential);
// Release pressure at start of minute
var newPressure = state.ReleasedPressure + state.PressurePerMinute;
// Compute new max
if (newPressure > maxPressure)
{
maxPressure = newPressure;
}
// Stop at minute 30
if (state.CurrentMinute == 30)
{
continue;
}
// Check if the valve can be opened
if (!state.OpenedValves.Contains(state.CurrentValve))
{
// New state with current valve opened
var openedValves = new HashSet<Valve>(state.OpenedValves);
openedValves.Add(state.CurrentValve);
paths.Enqueue(new ValvePath(state.CurrentMinute + 1, state.PressurePerMinute + state.CurrentValve.Rate, newPressure, state.CurrentValve, openedValves));
}
// Move to all accessible valves
foreach (var accessibleValve in state.CurrentValve.AccessibleValves)
{
paths.Enqueue(new ValvePath(state.CurrentMinute + 1, state.PressurePerMinute, newPressure, accessibleValve, state.OpenedValves));
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Max pressure released: [yellow]{maxPressure}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
throw new NotImplementedException();
}
private static Valve ParseValves()
{
var valves = new Dictionary<string, Valve>();
// Create valves first
foreach (var line in Input.ReadAllLines())
{
var span = line.AsSpan();
var nameStart = span.IndexOf(' ') + 1;
var name = span[nameStart..(nameStart + 2)].ToString();
var rateStart = span.IndexOf('=') + 1;
var rateEnd = span.IndexOf(';');
var rate = int.Parse(span[rateStart..rateEnd]);
valves.Add(name, new Valve(name, rate));
}
// Add links
// Create valves first
foreach (var line in Input.ReadAllLines())
{
var span = line.AsSpan();
var nameStart = span.IndexOf(' ') + 1;
var name = span[nameStart..(nameStart + 2)].ToString();
var valve = valves[name];
var valvesStart = span.IndexOf(',') != -1 ? span.IndexOf(',') - 2 : span.Length - 2;
var valvesToAdd = span[valvesStart..].ToString().Split(", ").Select(v => valves[v]);
foreach (var valveToAdd in valvesToAdd)
{
valve.AccessibleValves.Add(valveToAdd);
}
}
return valves["AA"];
}
#region Input
public const string ExampleInput =
"""
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II
""";
public const string Input =
"""
Valve JI has flow rate=21; tunnels lead to valves WI, XG
Valve DM has flow rate=3; tunnels lead to valves JX, NG, AW, BY, PF
Valve AZ has flow rate=0; tunnels lead to valves FJ, VC
Valve YQ has flow rate=0; tunnels lead to valves TE, OP
Valve WI has flow rate=0; tunnels lead to valves JI, VC
Valve NE has flow rate=0; tunnels lead to valves ZK, AA
Valve FM has flow rate=0; tunnels lead to valves LC, DU
Valve QI has flow rate=0; tunnels lead to valves TE, JW
Valve OY has flow rate=0; tunnels lead to valves XS, VF
Valve XS has flow rate=18; tunnels lead to valves RR, OY, SV, NQ
Valve NU has flow rate=0; tunnels lead to valves IZ, BD
Valve JX has flow rate=0; tunnels lead to valves DM, ZK
Valve WT has flow rate=23; tunnels lead to valves OV, QJ
Valve KM has flow rate=0; tunnels lead to valves TE, OL
Valve NG has flow rate=0; tunnels lead to valves II, DM
Valve FJ has flow rate=0; tunnels lead to valves AZ, II
Valve QR has flow rate=0; tunnels lead to valves ZK, KI
Valve KI has flow rate=9; tunnels lead to valves ZZ, DI, TL, AJ, QR
Valve ON has flow rate=0; tunnels lead to valves LC, QT
Valve AW has flow rate=0; tunnels lead to valves DM, AA
Valve HI has flow rate=0; tunnels lead to valves TE, VC
Valve XG has flow rate=0; tunnels lead to valves II, JI
Valve II has flow rate=19; tunnels lead to valves LF, NG, OL, FJ, XG
Valve VC has flow rate=24; tunnels lead to valves WI, HI, AZ
Valve VJ has flow rate=0; tunnels lead to valves UG, AA
Valve IZ has flow rate=0; tunnels lead to valves VF, NU
Valve EJ has flow rate=0; tunnels lead to valves ZK, LC
Valve DU has flow rate=12; tunnels lead to valves TC, UG, FM
Valve ZK has flow rate=10; tunnels lead to valves JX, EJ, JW, QR, NE
Valve XF has flow rate=25; tunnels lead to valves OP, VT
Valve LC has flow rate=4; tunnels lead to valves FM, EJ, ON, AJ, PF
Valve SV has flow rate=0; tunnels lead to valves XS, IY
Valve LF has flow rate=0; tunnels lead to valves II, OV
Valve DI has flow rate=0; tunnels lead to valves KI, BY
Valve OP has flow rate=0; tunnels lead to valves YQ, XF
Valve NQ has flow rate=0; tunnels lead to valves TC, XS
Valve QJ has flow rate=0; tunnels lead to valves VT, WT
Valve IY has flow rate=22; tunnel leads to valve SV
Valve AJ has flow rate=0; tunnels lead to valves LC, KI
Valve TE has flow rate=11; tunnels lead to valves QI, HI, KM, YQ
Valve ZZ has flow rate=0; tunnels lead to valves KI, AA
Valve VT has flow rate=0; tunnels lead to valves XF, QJ
Valve OL has flow rate=0; tunnels lead to valves KM, II
Valve TC has flow rate=0; tunnels lead to valves NQ, DU
Valve TL has flow rate=0; tunnels lead to valves VF, KI
Valve QT has flow rate=0; tunnels lead to valves AA, ON
Valve BY has flow rate=0; tunnels lead to valves DM, DI
Valve OV has flow rate=0; tunnels lead to valves LF, WT
Valve VN has flow rate=0; tunnels lead to valves RR, BD
Valve VF has flow rate=13; tunnels lead to valves OY, IZ, TL
Valve BD has flow rate=17; tunnels lead to valves NU, VN
Valve UG has flow rate=0; tunnels lead to valves VJ, DU
Valve PF has flow rate=0; tunnels lead to valves LC, DM
Valve RR has flow rate=0; tunnels lead to valves XS, VN
Valve AA has flow rate=0; tunnels lead to valves QT, ZZ, AW, VJ, NE
Valve JW has flow rate=0; tunnels lead to valves ZK, QI
""";
#endregion
}

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

596
Days/Day5.cs Normal file
View File

@@ -0,0 +1,596 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day5 : Day
{
public override int Number => 5;
public override string Name => "Supply Stacks";
private IDictionary<int, Stack<char>>? _stacks;
public override void RunPart1(bool display = true)
{
_stacks = InitStacks();
foreach (var line in Input.ReadAllLines())
{
var split = line.Split(' ');
var moveCount = int.Parse(split[1]);
var fromStack = _stacks[int.Parse(split[3])];
var toStack = _stacks[int.Parse(split[5])];
for (int i = 0; i < moveCount; i++)
{
toStack.Push(fromStack.Pop());
}
}
if (display)
{
for (int i = 1; i <= 9; i++)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
}
AnsiConsole.WriteLine();
}
}
public override void RunPart2(bool display = true)
{
_stacks = InitStacks();
foreach (var line in Input.ReadAllLines())
{
var split = line.Split(' ');
var moveCount = int.Parse(split[1]);
var fromStack = _stacks[int.Parse(split[3])];
var toStack = _stacks[int.Parse(split[5])];
// Push items in reverse order and remove them from the other stack
var items = fromStack.Take(moveCount).Reverse().ToArray();
foreach (var item in items)
{
toStack.Push(item);
fromStack.Pop();
}
}
if (display)
{
for (int i = 1; i <= 9; i++)
{
AnsiConsole.Markup($"[{(i % 2 == 0 ? "yellow" : "green")}]{_stacks[i].Pop()}[/]");
}
AnsiConsole.WriteLine();
}
}
#region Input
private static IDictionary<int, Stack<char>> InitStacks()
{
var stacks = new Dictionary<int, Stack<char>>
{
[1] = new("SLFZDBRH".Reverse()),
[2] = new("RZMBT".Reverse()),
[3] = new("SNHCLZ".Reverse()),
[4] = new("JFCS".Reverse()),
[5] = new("BZRWHGP".Reverse()),
[6] = new("TMNDGZJV".Reverse()),
[7] = new("QPSFWNLG".Reverse()),
[8] = new("RZM".Reverse()),
[9] = new("TRVGLCM".Reverse())
};
return stacks;
}
public const string Input =
"""
move 6 from 1 to 7
move 2 from 2 to 4
move 2 from 7 to 4
move 6 from 4 to 3
move 1 from 5 to 1
move 3 from 8 to 3
move 15 from 3 to 4
move 6 from 5 to 9
move 14 from 4 to 2
move 3 from 2 to 7
move 1 from 2 to 7
move 9 from 9 to 1
move 3 from 2 to 1
move 7 from 6 to 7
move 1 from 6 to 8
move 2 from 9 to 1
move 9 from 2 to 3
move 8 from 3 to 9
move 1 from 1 to 4
move 1 from 8 to 6
move 1 from 6 to 2
move 5 from 9 to 8
move 2 from 9 to 1
move 1 from 4 to 2
move 17 from 1 to 9
move 1 from 3 to 1
move 3 from 2 to 3
move 2 from 4 to 5
move 12 from 7 to 3
move 16 from 9 to 2
move 5 from 7 to 5
move 2 from 1 to 2
move 1 from 3 to 6
move 1 from 4 to 6
move 1 from 7 to 3
move 1 from 6 to 3
move 7 from 3 to 4
move 5 from 8 to 3
move 1 from 6 to 7
move 7 from 3 to 4
move 6 from 3 to 1
move 2 from 4 to 8
move 1 from 5 to 2
move 10 from 4 to 5
move 3 from 5 to 2
move 2 from 8 to 9
move 5 from 2 to 8
move 1 from 3 to 5
move 2 from 5 to 8
move 12 from 5 to 7
move 1 from 4 to 2
move 5 from 9 to 4
move 1 from 2 to 5
move 6 from 1 to 3
move 6 from 3 to 5
move 10 from 7 to 4
move 2 from 7 to 3
move 4 from 7 to 6
move 1 from 9 to 5
move 12 from 2 to 1
move 1 from 8 to 7
move 3 from 7 to 4
move 4 from 4 to 8
move 7 from 5 to 3
move 1 from 2 to 4
move 10 from 1 to 5
move 2 from 1 to 2
move 4 from 6 to 7
move 8 from 8 to 3
move 5 from 4 to 9
move 12 from 3 to 8
move 4 from 3 to 8
move 2 from 9 to 2
move 3 from 5 to 4
move 1 from 3 to 5
move 1 from 7 to 6
move 14 from 4 to 6
move 6 from 5 to 9
move 8 from 2 to 8
move 3 from 5 to 7
move 21 from 8 to 4
move 16 from 4 to 9
move 8 from 6 to 2
move 4 from 6 to 1
move 1 from 4 to 6
move 2 from 4 to 8
move 3 from 1 to 8
move 2 from 4 to 6
move 1 from 6 to 2
move 3 from 8 to 4
move 2 from 2 to 5
move 2 from 5 to 7
move 1 from 8 to 9
move 1 from 4 to 9
move 1 from 1 to 6
move 3 from 6 to 3
move 3 from 2 to 3
move 1 from 4 to 6
move 3 from 6 to 7
move 10 from 9 to 7
move 1 from 4 to 7
move 6 from 8 to 3
move 1 from 6 to 8
move 2 from 2 to 5
move 1 from 2 to 1
move 1 from 8 to 9
move 1 from 2 to 8
move 1 from 1 to 9
move 7 from 9 to 1
move 1 from 8 to 5
move 7 from 1 to 7
move 3 from 5 to 8
move 3 from 7 to 2
move 1 from 8 to 4
move 1 from 2 to 4
move 2 from 4 to 6
move 5 from 3 to 1
move 9 from 7 to 2
move 6 from 3 to 8
move 8 from 2 to 7
move 2 from 6 to 4
move 2 from 1 to 7
move 2 from 1 to 4
move 24 from 7 to 4
move 4 from 8 to 9
move 2 from 7 to 5
move 1 from 5 to 2
move 1 from 3 to 8
move 4 from 2 to 8
move 13 from 9 to 2
move 2 from 8 to 6
move 3 from 9 to 6
move 26 from 4 to 2
move 1 from 5 to 7
move 2 from 6 to 2
move 2 from 4 to 1
move 7 from 2 to 1
move 15 from 2 to 6
move 8 from 2 to 8
move 4 from 6 to 8
move 9 from 2 to 9
move 13 from 6 to 7
move 6 from 1 to 9
move 2 from 2 to 4
move 4 from 1 to 6
move 3 from 8 to 3
move 1 from 4 to 9
move 2 from 6 to 7
move 1 from 4 to 3
move 3 from 3 to 2
move 14 from 7 to 4
move 5 from 9 to 5
move 9 from 8 to 5
move 7 from 9 to 6
move 2 from 5 to 6
move 2 from 9 to 2
move 10 from 5 to 1
move 1 from 3 to 1
move 2 from 8 to 1
move 1 from 9 to 2
move 1 from 7 to 5
move 4 from 2 to 1
move 1 from 9 to 8
move 3 from 4 to 1
move 1 from 8 to 6
move 12 from 1 to 5
move 1 from 1 to 6
move 1 from 7 to 5
move 4 from 6 to 9
move 2 from 2 to 4
move 1 from 9 to 6
move 1 from 1 to 5
move 2 from 9 to 7
move 10 from 6 to 5
move 1 from 6 to 7
move 20 from 5 to 1
move 1 from 7 to 9
move 2 from 9 to 1
move 3 from 5 to 1
move 2 from 8 to 4
move 2 from 8 to 7
move 1 from 5 to 9
move 1 from 8 to 4
move 22 from 1 to 7
move 5 from 4 to 8
move 1 from 5 to 9
move 19 from 7 to 4
move 2 from 9 to 1
move 1 from 5 to 9
move 10 from 1 to 8
move 1 from 9 to 1
move 1 from 8 to 3
move 8 from 4 to 7
move 1 from 5 to 6
move 3 from 4 to 5
move 1 from 5 to 9
move 11 from 7 to 4
move 4 from 4 to 9
move 1 from 6 to 2
move 1 from 3 to 9
move 5 from 9 to 4
move 5 from 7 to 9
move 23 from 4 to 2
move 17 from 2 to 7
move 2 from 2 to 8
move 4 from 4 to 7
move 1 from 4 to 5
move 2 from 5 to 2
move 5 from 8 to 9
move 5 from 2 to 7
move 9 from 7 to 5
move 11 from 9 to 2
move 1 from 4 to 3
move 5 from 8 to 7
move 3 from 8 to 5
move 2 from 1 to 3
move 2 from 3 to 9
move 1 from 5 to 8
move 5 from 7 to 5
move 15 from 5 to 4
move 2 from 8 to 1
move 2 from 5 to 1
move 4 from 4 to 1
move 1 from 8 to 7
move 8 from 2 to 1
move 4 from 2 to 8
move 2 from 7 to 4
move 5 from 8 to 6
move 5 from 7 to 9
move 4 from 6 to 5
move 7 from 4 to 8
move 1 from 6 to 1
move 1 from 3 to 1
move 2 from 5 to 1
move 7 from 1 to 5
move 5 from 1 to 3
move 4 from 7 to 9
move 4 from 3 to 9
move 2 from 9 to 7
move 6 from 9 to 2
move 1 from 4 to 1
move 1 from 3 to 5
move 1 from 2 to 5
move 5 from 9 to 4
move 4 from 4 to 6
move 1 from 8 to 9
move 8 from 4 to 3
move 7 from 7 to 3
move 5 from 1 to 3
move 11 from 5 to 9
move 1 from 7 to 6
move 2 from 3 to 5
move 1 from 3 to 1
move 3 from 6 to 2
move 2 from 5 to 1
move 2 from 1 to 2
move 3 from 1 to 5
move 5 from 9 to 2
move 2 from 6 to 8
move 2 from 3 to 8
move 4 from 9 to 7
move 3 from 5 to 2
move 2 from 1 to 8
move 1 from 9 to 8
move 1 from 9 to 2
move 4 from 7 to 9
move 11 from 8 to 7
move 1 from 8 to 2
move 6 from 9 to 7
move 3 from 7 to 1
move 13 from 2 to 7
move 24 from 7 to 1
move 2 from 2 to 6
move 1 from 8 to 3
move 1 from 9 to 3
move 5 from 2 to 4
move 1 from 2 to 5
move 1 from 6 to 2
move 1 from 6 to 3
move 1 from 2 to 4
move 3 from 7 to 3
move 2 from 1 to 7
move 2 from 3 to 8
move 2 from 7 to 8
move 9 from 3 to 2
move 3 from 4 to 8
move 1 from 5 to 1
move 9 from 2 to 1
move 3 from 4 to 9
move 1 from 7 to 8
move 6 from 3 to 9
move 2 from 1 to 5
move 15 from 1 to 3
move 13 from 3 to 9
move 11 from 1 to 4
move 5 from 4 to 1
move 6 from 3 to 6
move 4 from 4 to 8
move 6 from 1 to 4
move 1 from 5 to 2
move 1 from 2 to 1
move 3 from 4 to 2
move 2 from 8 to 5
move 2 from 4 to 2
move 9 from 9 to 3
move 9 from 3 to 5
move 2 from 9 to 4
move 5 from 2 to 6
move 1 from 1 to 8
move 1 from 4 to 1
move 10 from 9 to 2
move 9 from 2 to 4
move 10 from 4 to 1
move 3 from 1 to 3
move 4 from 1 to 2
move 5 from 2 to 4
move 2 from 5 to 2
move 4 from 1 to 7
move 10 from 5 to 4
move 2 from 2 to 4
move 1 from 9 to 2
move 2 from 3 to 5
move 1 from 3 to 5
move 3 from 6 to 7
move 8 from 4 to 9
move 6 from 6 to 1
move 4 from 9 to 5
move 2 from 9 to 1
move 1 from 2 to 6
move 6 from 5 to 2
move 3 from 7 to 9
move 4 from 8 to 2
move 1 from 7 to 9
move 1 from 5 to 3
move 2 from 7 to 4
move 1 from 7 to 1
move 14 from 1 to 9
move 1 from 1 to 9
move 1 from 3 to 8
move 3 from 2 to 5
move 2 from 4 to 2
move 6 from 8 to 1
move 1 from 2 to 1
move 5 from 1 to 9
move 1 from 1 to 7
move 2 from 8 to 5
move 1 from 5 to 4
move 1 from 6 to 1
move 8 from 2 to 7
move 2 from 6 to 1
move 9 from 9 to 5
move 11 from 4 to 8
move 4 from 7 to 4
move 6 from 4 to 6
move 1 from 7 to 4
move 6 from 6 to 7
move 1 from 5 to 9
move 6 from 8 to 9
move 8 from 9 to 5
move 1 from 4 to 5
move 15 from 9 to 3
move 3 from 1 to 4
move 6 from 7 to 2
move 3 from 4 to 9
move 2 from 7 to 3
move 1 from 7 to 3
move 1 from 7 to 2
move 2 from 8 to 1
move 3 from 8 to 5
move 2 from 1 to 7
move 8 from 3 to 6
move 3 from 6 to 5
move 1 from 6 to 1
move 10 from 5 to 7
move 6 from 5 to 4
move 4 from 2 to 4
move 6 from 5 to 1
move 6 from 1 to 8
move 2 from 9 to 2
move 2 from 9 to 7
move 6 from 3 to 7
move 1 from 3 to 5
move 1 from 1 to 9
move 2 from 8 to 1
move 2 from 5 to 4
move 3 from 3 to 7
move 10 from 4 to 6
move 1 from 9 to 7
move 12 from 7 to 3
move 12 from 3 to 8
move 2 from 1 to 5
move 1 from 1 to 3
move 13 from 8 to 1
move 7 from 7 to 1
move 13 from 6 to 9
move 1 from 7 to 4
move 6 from 5 to 3
move 3 from 4 to 3
move 6 from 3 to 1
move 10 from 9 to 4
move 2 from 7 to 6
move 8 from 1 to 9
move 3 from 2 to 9
move 1 from 3 to 5
move 1 from 3 to 5
move 1 from 1 to 4
move 6 from 9 to 3
move 2 from 6 to 7
move 4 from 9 to 5
move 4 from 1 to 6
move 1 from 2 to 4
move 6 from 1 to 4
move 3 from 9 to 3
move 3 from 6 to 8
move 3 from 8 to 7
move 5 from 5 to 1
move 1 from 3 to 9
move 1 from 9 to 5
move 1 from 3 to 2
move 2 from 5 to 1
move 1 from 6 to 9
move 1 from 6 to 3
move 2 from 9 to 7
move 2 from 8 to 1
move 1 from 3 to 2
move 1 from 2 to 5
move 1 from 7 to 1
move 7 from 7 to 9
move 12 from 1 to 9
move 1 from 5 to 2
move 1 from 7 to 1
move 13 from 4 to 7
move 1 from 9 to 4
move 5 from 7 to 3
move 4 from 9 to 1
move 8 from 7 to 9
move 3 from 2 to 3
move 4 from 3 to 7
move 5 from 4 to 6
move 3 from 9 to 4
move 10 from 1 to 5
move 3 from 4 to 7
move 16 from 9 to 2
move 3 from 9 to 2
move 6 from 5 to 3
move 4 from 6 to 2
move 1 from 4 to 6
move 2 from 6 to 8
move 1 from 5 to 2
move 1 from 5 to 8
move 7 from 7 to 2
move 16 from 2 to 1
move 1 from 5 to 1
move 10 from 2 to 8
move 14 from 8 to 5
move 2 from 2 to 6
move 1 from 2 to 5
move 2 from 2 to 1
move 8 from 1 to 7
move 4 from 1 to 7
move 2 from 1 to 7
move 5 from 3 to 2
move 1 from 1 to 6
move 2 from 2 to 5
move 4 from 1 to 7
move 1 from 2 to 8
move 1 from 2 to 8
move 3 from 6 to 7
move 10 from 7 to 5
move 1 from 2 to 8
move 27 from 5 to 9
move 1 from 5 to 6
move 1 from 6 to 4
move 1 from 4 to 3
move 3 from 3 to 7
move 4 from 3 to 6
move 2 from 6 to 4
move 3 from 8 to 1
move 2 from 6 to 1
move 12 from 7 to 8
move 2 from 3 to 9
move 1 from 9 to 2
move 1 from 2 to 8
move 2 from 1 to 2
move 6 from 3 to 8
move 1 from 7 to 4
move 15 from 9 to 5
move 7 from 9 to 4
move 1 from 2 to 1
move 16 from 8 to 2
move 8 from 5 to 2
move 24 from 2 to 9
move 3 from 1 to 2
move 24 from 9 to 1
move 5 from 5 to 9
move 3 from 4 to 1
move 1 from 7 to 6
move 1 from 6 to 3
move 1 from 3 to 2
move 3 from 2 to 3
move 1 from 5 to 6
move 1 from 2 to 7
""";
#endregion
}

79
Days/Day6.cs Normal file
View File

@@ -0,0 +1,79 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day6 : Day
{
public override int Number => 6;
public override string Name => "Tuning Trouble";
public override void RunPart1(bool display = true)
{
int position = 0;
// Store the last 4 characters in a stream (kind of like a sliding window)
var charStream = new Queue<char>();
charStream.Enqueue(Input[0]);
charStream.Enqueue(Input[1]);
charStream.Enqueue(Input[2]);
for (int i = 3; i < Input.Length; i++)
{
charStream.Enqueue(Input[i]);
// Check if all 4 chars are different
if (charStream.ToHashSet().Count == charStream.Count)
{
position = i + 1;
break;
}
charStream.Dequeue();
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Position of start-of-packet marker is: [yellow]{position}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
const int length = 14;
int position = 0;
// Store the last 14 characters in a stream (kind of like a sliding window)
var charStream = new Queue<char>();
for (int i = 0; i < length - 1; i++)
{
charStream.Enqueue(Input[i]);
}
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)
{
position = i + 1;
break;
}
charStream.Dequeue();
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Position of start-of-message marker is: [yellow]{position}[/][/]");
}
}
#region Input
public const string Input =
"""
rgffbnnqvqhhmtmzzmmpmllcggsdswwvvwzzpptbppgngsnncwcnwcwnwgwrwrrnqnlqlccwggrcgrccjgcgwghgffjgjgrgmmsrrhchfcfdccjwwzdzcdcbcjjtfjjltlvvtstvttszsvsmmfccwcjwwzmzhhjvjpvjpppcwppdtdvtdvtvztzvzffdfqqgbgffrgrpgphhbcctssncsnncfcppvnpvnvfnfvnnfggtpplggwsggldllzvzrznncbbjpplbbrrnsrssmrsrhhmqmnqqhpqqnrqnrrtrnnrwrwhhpjhphlhvvgbgzztqtvvmssdshhqnhnjjvhjhqqbrqrrmrlrdllvrlvlccfvcffhfssgvsswhwqqfwfwhhcffjmmjrrbgrgjgrrvsrvvwmwsmmszzvmzvmmwmtthvvfbfllpjpwpwjpwpnpjpqqwtqtwwqpwqqrsqqcpqqssrgsrrjwwqmwmgwgrggmvmgmfgmffjfhjfjttcztccmtmmccnznhhcgcffmnfmmqjjhwwtccbzbhhwnhnsnmsnmnqqchhhnggbzbjzjzszsfsjfjvffnlffvrvddbhhqccdnnzwnznjnpnmppthhqddjhddqjqlqplqqjpjwppqttswsvwvfwflfplffnbfbwfwhhlhtlhtltzzmlmslmlwwgzwzrrwhhlnnrfnnmpppjpgpbbhpbhppbrppbhhzgzczqcqvqggwppcnnhnznvznzhhcpctptpjtppdhhprhrcrpcprpplrprzrnrfnrnlrlvrrfqqnnsqsqrssnrnvvvghvvbzzqppjsjnnrprwrrmqqtfqfwwrdrsddprddbdzbdbndbdjdljjrtjrrnzrzjrzzpssftfmfbflbbcpcsppwrppntnhthlthtbbsmsbmsmggpssnhnjjtsjjwssdjdwwppcbpcclmccwzzrggmgmnnwjnnqppjttvllmhhvcctptbpbdpdhdqqgggbnnqcchlhssltstllvqlvqvdvjdvvqvsvfvhfhlfftqffztzdttfvvzmvzznvnsnjjvqjvjljplpvvzlzhzghgddbbzbmbnztgthrnpsqhhdvprtpdftmqfvgjzgdvqwmvgwbczvbschqfhdvqcfnmbgmtqmlmsqcbfhshrzzbrtpgnwwtzgnjghzrlwhntprqhvshjcfvlnchccbtnswfnmpccdppqrqrhngvlwrpplbnpgzbzwtzwrsptmsmlndcfmbnqgvnqvzwpvrtfsrwfvfwdvplrfdddwcnwhzchmwfjsfvbtbrjchmgqwfvvmpzhqcbzhrcmjrzmgrtnzrcqdqdqnpwjctlhrjcphbbcvhvqnhtwjrvrbzfzfzzplshvrcchvtgtjcnhlzsttwdhcmdvrdlgsngvtzqsjrcptwwbgvfbsvgnmfhmvgqtfzbhhmdznjlsghhnlwzhvplfvlqzbrsjhdvrshjbnfqgpscbpzmnmmcsdbtwbwmsvfjwdvtctslcqfssrhczdptlrjbfzjctqrcbppcfcbqqzhhftdjchtscwgwcnpvrrjvnnwrqtrqmbgdfcpqhddnvdnmlmqcgsndwbcfvfrzsrflsnqrpmszqrdlshlcsfrmnsqmtrvjwqcllftscwrtmvcjsmrlqvdfjzgfdtswqzldqgjvhczpqrfbclnbwcjprjncvhgfmjhgfgnvfzfnvbbstgsgtspdhtfsncttlwmllbbvqftjtshfjlqtjwlvrbwmzfhdmcbhtqdzqtzmdljqprwhqwcvbtfqbpjwztgqrvlrqdwmqrqzvptsgjdqnqdfwfpjdglwgpdrcfrrzmpjmtbwwrqqcsnmphcqtthlnlzlfftrjmtjwwqrldcfjjclzrsqvltsfchfggcwbzbtpqcjfvgpwnwwqrdbdvjplgsgctdhqvttmtpmmjfcqdslhjgtdppbmzbrfbrrjncfdhlmjgdwjrmbgpcgctghbvphpgfvvfvtplqrhnjjhqntjvbsggvrvjgrwptcgqgrmjtprvhnvjsdsfqrqrrltlhvfsjsqpbwndbsnjzplcfqtfbdqdzdvnljcsmjnrmwwjzqwsjbdlclsmccbqwnlpltqhqhmthhrdjwlqwrbltghsvblqntvjqzpmmpqwrrwvhmtfqzhrmjfglwfpthhgbhdmrtprtqgqbdcfqlbbvmzmchzglmpzdvhpqchhclbcvrcmhtzqfzrplbvmdhghsttzgdjbgmmtvlqjsstgwlwchhwmflwbgljgszghvfdsngbtbcnhzmmdmsjqfbcsmgpjwjqgwqdlrgznnmhphbrzcgnqczpcbljjmhnnrmzlpqbswwcjpjqcrtdmgprpmmbprwlmpzcmwlnbzqjsgftrncvmjmjwvqgszsrmrczhjnwlghgndhbthwlhfbncrwqfgnshrmdfhwmfvllhvbmmllwfbgrnrttpzffzvcfjfbrmdqfcfrdqsltpbbttnqnbncfhwghfbgwrltbhwmmlpczsvvdnwhchgfplnjsttsqvsznwvlwzgfnhfrrgplsfwrwnbfhblwtjpldjmzrglhppgsjsgzssbbgrrbdmpwhgjjmlfnpdbvtntcwrvltgfnrgwttvvjhqljjvvnmztwgzcclgbjnjspzwnpgtgvhhhqbzrnvmdcljcdncvpnpdhrhqwvlhllbsrmjbzlgczwjsrvqrqfqmtjrnpbtdhsrfbhrgtgnrmlgcwcmrvrdfcqbfcqczjchgrjpzqfqqmcpvnvbrssfrfsrjmlngplqqsnclgvpfhjbzdppjftlgbmcgdbrvqrclvtdnzhhcmzlrdrgbrqrlvfcnvznnqwswvhdpbbjmsqzcrmjngzmdftjzsjvgfdtcvdwhnwwjlcgcmflzzpzpgzrvmptbjgrdjbzscrglhcjppdjdshnvvbsnnddtbwsdrpnbnlrtppcrzbbjrfzhbwgmjqtmgjvmrjgfdndlmqvhgwprsjnhcmrnfdfdzggjjzcccnsnwwbjzmsfjjfhclptfcwqjhnphpwzszjmsrtnbqpqsvcfcvrrgclwlbrqngdcdlzrdfpvbgtznjzdvjngrgswhjnrpgswtqflpgvnpbsvcrtgtzcbhdjpbjwnpdzcmprtzlppbqvpzrrlbssmwhhvqqpmwggnzwcfdnzccjrrncnvjqgbpstctwpqvhdsbcsjrpbzbdlwwvjngtbnvpthppglgsnrbwnvpzldhsgwqhclgwrdsvcfdclvdsbrhcfnbgrtqswstnjfmfrdgphpvgjfqzcwnpcghdhtflgdnhhnnnwrpnmppszgqdcqjqpnccfsqjsmwtqvzwfqvtwtthwswmcqqcqjwcgwgzgmnpzbfpzrqbvqhbhtsvvbppbmqzfnsmwppzvsctgcncztsqdfhnlwjjtvwcchvnphwpnpzqsjhlrcmnbthtqlfclnsfdtpwfzljdpfszvhgzdpzhbjtphbfbmwgfrfplntfqhgpbjzghmblzzhdcbptngqwrtfmvtbhphpvdwpswbscrwzhnvqfwlbwwqqgstgmbqlllspbhbpjmmrfhmjwzdnsdwmpvlrspgzmdjwqwcjpbgwspsghjdvrbbsbtgwptqdvvdhbhqbdhpbzdsdwsjdbjnztdqqrdhwhtpvcbblbmjgmbpqghdsfthzjffrdvldfsnpcsmnzwzcqlnvcrcbqnfcdrfbffrvhqsbqjnnbzsqvqqdqwmsvbqvtgmnnlthpngfsljqnrdhhzpmwsnqvrgdnvlbgnndfcpjfgmzqssvnnrwbmslcqpnhnnwzggsjvqcsqpfzjcmcppntmsdtfggzdncqbfjsqvbzgnnlsdbgjqffsmvnbqlsrjwdmcjbrsrpchnnhdtlcdhfdltmlvtrwjpzphtbhzzrlrwbbhhpntgbcfmphnbrjdhrhvmvhfglrncngjdsvbfrqtqzsgvlzjqzcqnwdcfgvnpsqpphwfsdvpgnchjnnjhsqgvlqcvhzzzcrsqcvrbsbjbdbgddlbb
""";
#endregion
}

1250
Days/Day7.cs Normal file

File diff suppressed because it is too large Load Diff

314
Days/Day8.cs Normal file
View File

@@ -0,0 +1,314 @@
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day8 : Day
{
public override int Number => 8;
public override string Name => "Treetop Tree House";
public override void RunPart1(bool display = true)
{
var grid = CreateGrid();
var valid = new HashSet<(int, int)>();
// Check each line from left to right
for (int i = 0; i < grid.GetLength(0); i++)
{
int previousTreeSize = -1;
for (int j = 0; j < grid.GetLength(1); j++)
{
var size = grid[i, j];
// The tree on the left is blocking the view, stop searching on this line
if (size <= previousTreeSize)
{
continue;
}
valid.Add((i, j));
previousTreeSize = size;
}
}
// Check each line from right to left
for (int i = 0; i < grid.GetLength(0); i++)
{
int previousTreeSize = -1;
for (int j = grid.GetLength(1) - 1; j >= 0; j--)
{
var size = grid[i, j];
// The tree on the left is blocking the view, don't take it
if (size <= previousTreeSize)
{
continue;
}
valid.Add((i, j));
previousTreeSize = size;
}
}
// Check each column from top to bottom
for (int j = 0; j < grid.GetLength(1); j++)
{
int previousTreeSize = -1;
for (int i = 0; i < grid.GetLength(0); i++)
{
var size = grid[i, j];
// The tree on the top is blocking the view, stop searching on this column
if (size <= previousTreeSize)
{
continue;
}
valid.Add((i, j));
previousTreeSize = size;
}
}
// Check each column from bottom to top
for (int j = 0; j < grid.GetLength(1); j++)
{
int previousTreeSize = -1;
for (int i = grid.GetLength(0) - 1; i >= 0; i--)
{
var size = grid[i, j];
// The tree on bottom is blocking the view, stop searching on this column
if (size <= previousTreeSize)
{
continue;
}
valid.Add((i, j));
previousTreeSize = size;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Total viewable trees: [yellow]{valid.Count}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var grid = CreateGrid();
var maxScenicScore = 0;
// Compute scenic score for each tree
for (int i = 0; i < grid.GetLength(0); i++)
{
for (int j = 0; j < grid.GetLength(1); j++)
{
var size = grid[i, j];
var score = ComputeScenicScore(grid, i, j, size);
if (score > maxScenicScore)
{
maxScenicScore = score;
}
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Max scenic score: [yellow]{maxScenicScore}[/][/]");
}
}
private int ComputeScenicScore(int[,] grid, int i, int j, int size)
{
var visibleTreeCountLeft = 0;
var visibleTreeCountRight = 0;
var visibleTreeCountTop = 0;
var visibleTreeCountBottom = 0;
// Look on left
for (int x = j - 1; x >= 0; x--)
{
visibleTreeCountLeft++;
var nextTreeSize = grid[i, x];
// Blocking the view
if (nextTreeSize >= size)
{
break;
}
}
// Look on right
for (int x = j + 1; x < grid.GetLength(1); x++)
{
visibleTreeCountRight++;
var nextTreeSize = grid[i, x];
// Blocking the view
if (nextTreeSize >= size)
{
break;
}
}
// Look on top
for (int y = i - 1; y >= 0; y--)
{
visibleTreeCountTop++;
var nextTreeSize = grid[y, j];
// Blocking the view
if (nextTreeSize >= size)
{
break;
}
}
// Look on bottom
for (int y = i + 1; y < grid.GetLength(0); y++)
{
visibleTreeCountBottom++;
var nextTreeSize = grid[y, j];
// Blocking the view
if (nextTreeSize >= size)
{
break;
}
}
return visibleTreeCountLeft * visibleTreeCountRight * visibleTreeCountTop * visibleTreeCountBottom;
}
private int[,] CreateGrid()
{
var lines = Input.Split('\n').Select(s => s.Trim()).ToArray();
var grid = new int[lines.Length, lines[0].Length];
for (int i = 0; i < grid.GetLength(0); i++)
{
for (int j = 0; j < grid.GetLength(1); j++)
{
grid[i, j] = int.Parse(lines[i][j].ToString());
}
}
return grid;
}
#region Input
public const string Input =
"""
220102001303332210111144403232401113333122342344231242454143210203320302212443030013122003001101100
002012111323310331302003042221132010432132445255133124455255223004414440440003301012203200022100210
200201202011003110423331304200331011531224544245554512113213335525210302033141324322321031312102110
100020212221032131124244103404003222433224521422334123232422124515312313433224100204010121132311000
200113321032110240111004030043155443522233113242534443312241445211112450323031312112213000023232100
000123222130133422212242344055134444215311551422533215421415442551425225432130430124043210211111310
220013001310041302023441034332322423241253523413533421512551432233114553552003013120121302130121320
103122021001324130041021443134551553414353255343356623553131221454542451225451442032131420112320101
012123121220242033212021343121244143344324534625253522262464534215422121222134240012234133102111220
330310331223230000003152443554413335326665536266322522652335566553114314142351411020403401413302112
033203120011110011132251145135331144533354253453463224233644324632453434135523253300131220303213123
320111230330142103134512313345346434643654336344264466663434525446644113511452351451422214014013322
001132233321313303345535112443242622242446334234425332545346556362543355243332135453212444110331303
112033313244310423153325243233225655536462366623456645652435535435325433454445524512423111021132122
313313043314211444453212142362452645555543222645663664243443432442223333565131234141351344321344102
131230133213133211232332525334634543566623665537334334547734623265434432455254451425235432443212211
033344041000113254352455455346236225633465644343664557364344535543336532242444234311533433344140212
213210413044552341333323656654354424366446744766744473434577534775255332236334522521333331002022121
223112203001555435245233523555243667443447767433564533557556755677732432236462355155425414244240300
031112340101154335334634566542526467535374465476634474475365364377737233444423444335143215320411041
010203132113252122424352345322745777347553756767766736766655557657446763326426264545545441510322304
321034434351253424555342636457546533636345766763737363536656637564757633453436366225532223151301123
140333103113245552456543556436376775537436555564765867677377566536736367466446544545111231522432042
344202325543255413523362252766476773354345756567775846446585764655346457333656245566142114252141442
300442033331415536626644654454735373634646576484854768867856765345656633644236246242335514321313432
422444251112412665556253554536437336675554766648744646768865576456545754676632532244262315154431312
202304543452455552253665657746647784558765457564785778845788767784833536336745445354462312521531440
443202253112536253525354345435633886668445868754667447674764886554756567546737654246334325241222041
444423415155442365223265743454556684558776766888858567565767784775755635475565754224462452335222241
344303321125225553466564654375755674684544768955877976656855558645744675543644552655335222244234041
300235531322254555657355344757787845684787759755989576658884775746464854347454745445252251123331200
202355355135453623555734775437867546864765789685787875887555685885564677653753475626332543431524440
123112125155234436477477667347767767746589595765887578895688659457644647637353775542533353231324344
410231223354354564265577744565557576558859695696978987776856795557766747576576743622336235154122541
144345221145432366464547578854445477995896778965569886979678656986544557875776343376245336222211154
041355524153432432536456778856655655586558689789676558987567866689878584574356765462664355555422315
043213424536224446535754387584686658555998969679778967988975666897764557557733673744622262412325233
101514245332544663477377677875765977975768579996797978899567698975768865784644537776543454651544223
055515332353232236436447686544477656596959996666689896787797795969665874555543664764442344265232243
222545542226664544634434558757485778565956766669899769668998978795896868888674777634532432531545351
434314333334362377634654477865886799965779778887799678789966958767788684856666356767346645644343444
052335546342344533746576644847456965678786776877897777697767787998596844688878543443425354265524523
245321436235332754756734464668569895557967788998689969678678888859577664555777765333674636253522234
222511135542326767344777655475586999669889777967697967976779776769789666884457455657536456246131555
254433214252433545454764655656756765598866789679798998989699886966798756574757563674433652342254411
252443455634345774563668584548569877777679776897897977978768868758769758655687433345452443435424512
312151563634655557774676587765775678576967989777779888989698876657887877756744456665655635556644123
255315424526333665355778666668586665799969869877998777889777988668875966868565465457776522236513141
141324353246555364776377784867669969887687879788978777778977696768597689744655653757436644265454325
354554356562633675467576477485995977969979699799889979879876989688558895876557644555777244452335314
235324556262356365436555887646778779897999678779989989789867689977685966845857674434347554655643252
413432246554227346473675665849975567696667989798798778788967877675576875667875866434546262246521543
552324452542255347547654567456656665796776679978889979999797899897878689747764654756336634422352455
132142446224635664776385465487598668797987978789877989998967699965559668558447437465553652345225512
535121326642222474774354544766768756799778998798789898877898889965958696446887843476762526426515244
345151122435326774546477755588766796667978679897798799788798667756596585444845757774352236466242124
324135422245435777577646446776855665599676997689997887788889876766665986567668467764463526524522524
325343515546653536653454765454579566578777977788879878787979966579696677474785343347473444324354355
411221244324436736446567757755797766577698989699898679769679676797557885877546755664674522365314215
011225512566433343766434774658485575577887896689896789789788897667989867646846655537445534555245154
353122224246523453336574684477667558859686788676888887889677967668868867745484457553323245424151214
025211533334552466553436874465855779555988968677869768998666855765958765844553645533522566662215435
011144555564545656657564766665457958988879979779789696768889888785895588848586367454333255641115431
312135513646235366335766645784546897755855986679986669787888667577687576776674647476324553225412153
401131435555652456777737485558685475567889776796686996966887777867565457675674635564364663332115334
111542111546535443776533554556858445867565786988765999858788986988467667765674337645225253433114412
324152522543244453747533764587454556659676798855686758699569787576577568846344576564242526335344431
123513525116652325364735577676854466795879775965858579978758766786788576585574533555234644544424444
201422231514666656435556464744556487779676697575668797755696587875664885475643663462362633532152224
443133412441244332664735557756557478667877999697777576977768645754645558333564346654626425334525344
431015242443666335263335435575686474856864565688697865686896558787678553436564534565256645251434512
010022255222133364253766673665475577467776484765858776654564844676776444447654375652434614143215022
112002141144134663334274465647734767886457477454887888474577867446657475453544742245245225443332224
331232153352336525225567445365565486747774487468877475878758554778586376763333443326544225345123013
320123541455416433363426343365775545857885758565575848877877686547673556675754423464442514232324111
042432343324232554524246554574474345666464658776446546567878767443577744556362465553665411142432422
142111123322431534522545253754364545474457775847846786887674646573467346333352524442333115335223141
344133332441235422454233333556736343777476764657687856476465776533456554442553426542432524345343333
200031013552112555654336435633347655674473538755855765665344475745556736546535462654344221551230302
304022204315531423544354645467655764773637456746376536645753764476654735362436623665431353330033320
001214000225135351445433524663673656735567443667544556374445736766637732424362445435124235202421144
133240444115255522316642262344554645657446334644647444534543345455733253453543223511253231133210321
324313341004114352115254632235242543363566666546735757746734646346355536356645334223223155213043334
322012103401425423541123244634634342577565467364645454366476547536536356344363313411143511003322321
030233343013121433455142565364335554237444577544465747334546363663525346435245514412331312412441220
210201421410133422542335534522343332455655473755663556635632662655563553445642432325453033042340112
012224401212432145413124536446542562653225343456763356434464356455233544345355532151231212104022112
312232323430402414252325451525553345425256326265324326656464322435443535213233315511433100124021321
010230232102113031224241215434543254266544664634225463436365465636465234441113521431122331212121101
212212302203143433332245352152333246623456656325435343642442543354454522241344343333411433411331230
011102200023414304323524211214225553365332454633645434256444354263245252314454334421304444012133303
120113010124021413002342554241434235565233233626345455655236425423152444344321441224210011210001020
101033322321412021400115241224135351431466535533654236552223322311141154321444212340220200110122301
011220031300131001424314223221135334414132553352224226351421342145342332444324224232200001102210233
121312303322224212003013214154522352135431322413434142221234334123523122531033230010321012211132201
012020110022314203102101331443513341244141113213442111455332441213534235144341443443042312110221221
100013222332201123334301101412554224524144445454322353452424512151232340130231214403422202221333120
211200011012011223124042241233103554151124335225451435512351451314113131210120200021021301331230211
222211000301233212310103403144201411351211113145331241322345244155131304344032001313100223022021012
""";
#endregion
}

2149
Days/Day9.cs Normal file

File diff suppressed because it is too large Load Diff

25
EnumerableExtensions.cs Normal file
View File

@@ -0,0 +1,25 @@
namespace AdventOfCode;
public static class EnumerableExtensions
{
public static IEnumerable<TSource> Flatten<TSource>(this TSource root, Func<TSource, IEnumerable<TSource>> flattener)
{
var toVisit = new Stack<TSource>();
toVisit.Push(root);
while (toVisit.TryPop(out var node))
{
yield return node;
foreach (var child in flattener(node))
{
toVisit.Push(child);
}
}
}
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
}
}

BIN
Preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -1,22 +1,59 @@

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)!);
var select = new SelectionPrompt<Day>()
.Title("[cyan]Select a [yellow]day[/] to run:[/]")
.AddChoices(days);
.AddChoices(days.OrderByDescending(d => d.Number));
var selectedDay = AnsiConsole.Prompt(select);
var stopWatch = new Stopwatch();
AnsiConsole.MarkupLine($"[cyan]Running [yellow]{selectedDay}[/]...[/]\n");
AnsiConsole.MarkupLine("[cyan]Part [yellow]1[/] result:[/]");
selectedDay.RunPart1();
try
{
stopWatch.Start();
selectedDay.RunPart1();
stopWatch.Stop();
AnsiConsole.MarkupLine($"[red]Approximate run time: [yellow]{stopWatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000:F3} ms[/][/]");
}
catch (Exception e)
{
AnsiConsole.WriteException(e);
}
stopWatch.Reset();
AnsiConsole.MarkupLine("\n[cyan]Part [yellow]2[/] result:[/]");
selectedDay.RunPart2();
try
{
stopWatch.Start();
selectedDay.RunPart2();
stopWatch.Stop();
AnsiConsole.MarkupLine($"[red]Approximate run time: [yellow]{stopWatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000:F3} ms[/][/]");
}
catch (Exception e)
{
AnsiConsole.WriteException(e);
}

15
README.md Normal file
View File

@@ -0,0 +1,15 @@
# Advent of Code
![CLI Preview](Preview.png)
Advent of Code made in **C#**, using **[Spectre.Console](https://spectreconsole.net/)** for **console display** and **[BenchmarkDotNet](https://benchmarkdotnet.org/)** for **benchmarks**
## Build and run
- **Install [.Net 7 SDK](https://dotnet.microsoft.com/en-us/download)** if needed
- **Clone** the repository
- In a shell, execute `dotnet run`
## Benchmarks
> Todo...