diff --git a/Days/Day21.cs b/Days/Day21.cs new file mode 100644 index 0000000..dcd37b0 --- /dev/null +++ b/Days/Day21.cs @@ -0,0 +1,183 @@ +using System.Collections.Frozen; +using System.Numerics; +using System.Runtime.Intrinsics.X86; +using System.Text; +using Spectre.Console; + +namespace AdventOfCode.Days; + +public class Day21 : Day +{ + public override int Number => 21; + public override string Name => "Keypad Conundrum"; + + private const char Up = '^'; + private const char Right = '>'; + private const char Down = 'v'; + private const char Left = '<'; + private const char Enter = 'A'; + + private readonly Dictionary _numpadPositions = new() + { + { '7', (0, 0) }, + { '8', (1, 0) }, + { '9', (2, 0) }, + { '4', (0, 1) }, + { '5', (1, 1) }, + { '6', (2, 1) }, + { '1', (0, 2) }, + { '2', (1, 2) }, + { '3', (2, 2) }, + { '0', (1, 3) }, + { Enter, (2, 3) } + }; + + private readonly Dictionary _keypadPositions = new() + { + { Up, (1, 0) }, + { Enter, (2, 0) }, + { Left, (0, 1) }, + { Down, (1, 1) }, + { Right, (2, 1) } + }; + + public override void RunPart1(bool display = true) + { + var codes = ParseCodes(); + var complexitiesSum = 0; + + foreach (var code in codes) + { + // Get first keypad sequence + var firstKeypadSequence = new StringBuilder(); + var currentInput = Enter; + + foreach (var digit in code) + { + firstKeypadSequence.Append(GetNumpadMoveSequence(currentInput, digit)); + + currentInput = digit; + } + + // Get second keypad sequence + var secondKeypadSequence = new StringBuilder(); + currentInput = Enter; + + foreach (var input in firstKeypadSequence.ToString()) + { + secondKeypadSequence.Append(GetKeypadMoveSequence(currentInput, input)); + + currentInput = input; + } + + // Get third and last keypad sequence + var thirdKeypadSequence = new StringBuilder(); + currentInput = Enter; + + foreach (var input in secondKeypadSequence.ToString()) + { + thirdKeypadSequence.Append(GetKeypadMoveSequence(currentInput, input)); + + currentInput = input; + } + + complexitiesSum += thirdKeypadSequence.Length * int.Parse(code.AsSpan()[..^1]); + } + + if (display) + { + AnsiConsole.MarkupLine($"[green]Sum of complexities: [yellow]{complexitiesSum}[/][/]"); + } + } + + public override void RunPart2(bool display = true) + { + + } + + private string GetNumpadMoveSequence(char origin, char destination) + { + var originPosition = _numpadPositions[origin]; + var destinationPosition = _numpadPositions[destination]; + + var move = destinationPosition - originPosition; + + var moveRight = move.X > 0; + var moveDown = move.Y > 0; + + var sequence = string.Concat( + new string(moveRight ? Right : Left, Math.Abs(move.X)), + new string(moveDown ? Down : Up, Math.Abs(move.Y)), + Enter.ToString() // Always end on Enter to press key + ); + + return sequence; + } + + private string GetKeypadMoveSequence(char origin, char destination) + { + var originPosition = _keypadPositions[origin]; + var destinationPosition = _keypadPositions[destination]; + + var move = destinationPosition - originPosition; + + var moveRight = move.X > 0; + var moveDown = move.Y > 0; + + var sequence = string.Concat( + new string(moveDown ? Down : Up, Math.Abs(move.Y)), + new string(moveRight ? Right : Left, Math.Abs(move.X)), + Enter.ToString() // Always end on Enter to press key + ); + + return sequence; + } + + private List ParseCodes() + { + var codes = new List(); + + foreach (var line in Input.AsSpan().EnumerateLines()) + { + codes.Add(line.ToString()); + } + + return codes; + } + + private readonly record struct Point(int X, int Y) + : IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators + { + public static Point operator +(Point left, Point right) + { + return new Point(left.X + right.X, left.Y + right.Y); + } + + public static Point operator -(Point left, Point right) + { + return new Point(left.X - right.X, left.Y - right.Y); + } + + public static Point operator *(Point left, int right) + { + return new Point(left.X * right, left.Y * right); + } + + public static Point operator *(int left, Point right) + { + return new Point(right.X * left, right.Y * left); + } + + public static implicit operator Point((int X, int Y) point) + => new(point.X, point.Y); + + public int DistanceTo(Point other) + { + var distance = other - this; + + return Math.Abs(distance.X) + Math.Abs(distance.Y); + } + } +} \ No newline at end of file diff --git a/Inputs/Day21.txt b/Inputs/Day21.txt new file mode 100644 index 0000000..dd73dfd --- /dev/null +++ b/Inputs/Day21.txt @@ -0,0 +1,5 @@ +029A +980A +179A +456A +379A \ No newline at end of file