diff --git a/01/Trebuchet/Program.cs b/01/Trebuchet/Program.cs index 46e5e1d..32d2d3f 100644 --- a/01/Trebuchet/Program.cs +++ b/01/Trebuchet/Program.cs @@ -1,4 +1,5 @@ -using System.Text.RegularExpressions; +using System.Diagnostics; +using System.Text.RegularExpressions; namespace Trebuchet; @@ -23,9 +24,15 @@ public class Program : new PartOnePuzzleSolver(); var input = await File.ReadAllLinesAsync(args[0]); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var result = puzzleSolver.SumCalibrationValues(input); - Console.WriteLine($"The sum of all calibration values is {result}."); + stopwatch.Stop(); + + Console.WriteLine($"The sum of all calibration values is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); return result; } diff --git a/08/HauntedWasteland.Tests/MapTests.cs b/08/HauntedWasteland.Tests/MapTests.cs new file mode 100644 index 0000000..6373d76 --- /dev/null +++ b/08/HauntedWasteland.Tests/MapTests.cs @@ -0,0 +1,65 @@ +namespace HauntedWasteland.Tests; + +public class MapTests +{ + [Theory] + [MemberData(nameof(TestData.ParseMapTestData), MemberType = typeof(TestData))] + public void Parse_WhenGivenStringArray_ItShouldReturnMap(string[] input, Map expected) + { + Map.Parse(input).Should().BeEquivalentTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.CountTurnsTestData), MemberType = typeof(TestData))] + public void CountStepsToZ_WhenGivenMap_ItShouldReturnNumberOfSteps(string[] input, int expected) + { + Map.Parse(input).CountStepsToZ().Should().Be(expected); + } + + public static class TestData + { + private static readonly string[] MapInput = + [ + "RL", + "", + "AAA = (BBB, CCC)", + "BBB = (DDD, EEE)", + "CCC = (ZZZ, GGG)", + "DDD = (DDD, DDD)", + "EEE = (EEE, EEE)", + "GGG = (GGG, GGG)", + "ZZZ = (ZZZ, ZZZ)", + ]; + + public static IEnumerable CountTurnsTestData => + new List + { + new object[] + { + MapInput, + 2 + }, + }; + + public static IEnumerable ParseMapTestData => + new List + { + new object[] + { + MapInput, + new Map( + ['R', 'L'], + [ + new("AAA", "BBB", "CCC"), + new("BBB", "DDD", "EEE"), + new("CCC", "ZZZ", "GGG"), + new("DDD", "DDD", "DDD"), + new("EEE", "EEE", "EEE"), + new("GGG", "GGG", "GGG"), + new("ZZZ", "ZZZ", "ZZZ"), + ] + ) + }, + }; + } +} \ No newline at end of file diff --git a/08/HauntedWasteland.Tests/NodeTests.cs b/08/HauntedWasteland.Tests/NodeTests.cs new file mode 100644 index 0000000..4a3fcca --- /dev/null +++ b/08/HauntedWasteland.Tests/NodeTests.cs @@ -0,0 +1,54 @@ +namespace HauntedWasteland.Tests; + +public class NodeTests +{ + [Theory] + [MemberData(nameof(TestData.ParseNodeTestData), MemberType = typeof(TestData))] + public void Parse_WhenGivenString_ItShouldReturnNode(string input, Node expected) + { + Node.Parse(input).Should().BeEquivalentTo(expected); + } + + public static class TestData + { + public static IEnumerable ParseNodeTestData => + new List + { + new object[] + { + "AAA = (BBB, CCC)", + new Node("AAA", "BBB", "CCC") + }, + new object[] + { + "BBB = (DDD, EEE)", + new Node("BBB", "DDD", "EEE") + }, + new object[] + { + "CCC = (ZZZ, GGG)", + new Node("CCC", "ZZZ", "GGG") + }, + new object[] + { + "DDD = (DDD, DDD)", + new Node("DDD", "DDD", "DDD") + }, + new object[] + { + "EEE = (EEE, EEE)", + new Node("EEE", "EEE", "EEE") + }, + new object[] + { + "GGG = (GGG, GGG)", + new Node("GGG", "GGG", "GGG") + }, + new object[] + { + "ZZZ = (ZZZ, ZZZ)", + new Node("ZZZ", "ZZZ", "ZZZ") + }, + }; + } +} \ No newline at end of file diff --git a/08/HauntedWasteland.Tests/UnitTest1.cs b/08/HauntedWasteland.Tests/UnitTest1.cs deleted file mode 100644 index a3f19b5..0000000 --- a/08/HauntedWasteland.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace HauntedWasteland.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file diff --git a/08/HauntedWasteland/Program.cs b/08/HauntedWasteland/Program.cs index 3751555..9f7c8a1 100644 --- a/08/HauntedWasteland/Program.cs +++ b/08/HauntedWasteland/Program.cs @@ -1,2 +1,106 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +using System.Diagnostics; + +namespace HauntedWasteland; + +public class Program +{ + public static async Task Main(string[] args) + { + if (args.Length is 0) + { + Console.WriteLine("Please provide a path to the input file."); + return -1; + } + + if (File.Exists(args[0]) is false) + { + Console.WriteLine("The provided file does not exist."); + return -2; + } + + var input = await File.ReadAllLinesAsync(args[0]); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var result = Map.Parse(input).CountStepsToZ(); + + stopwatch.Stop(); + + Console.WriteLine($"The number of steps to Z is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + + return result; + } +} + +public class Map( + List turns, + List nodes +) +{ + public List Turns { get; init; } = turns; + public List Nodes { get; init; } = nodes; + + public static Map Parse(string[] mapInput) + { + var turns = mapInput[0].ToList(); + var nodes = mapInput[2..] + .Select(Node.Parse) + .ToList(); + + return new Map(turns, nodes); + } + + public int CountStepsToZ() + { + var current = Nodes.First(n => n.Current == "AAA"); + var steps = 0; + + while (current.Current != "ZZZ") + { + var next = Turns[steps % Turns.Count] switch + { + 'R' => current.Right, + 'L' => current.Left, + _ => throw new Exception("Invalid turn") + }; + current = Nodes.First(n => n.Current == next); + steps++; + } + + return steps; + } +} + +public class Node( + string current, + string left, + string right +) +{ + public string Current { get; init; } = current; + public string Left { get; init; } = left; + public string Right { get; init; } = right; + + public override string ToString() + { + return $"{Current} = ({Left},{Right})"; + } + + public static Node Parse(string nodeString) + { + var parts = nodeString.Split( + '=', + StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries + ); + var current = parts[0]; + var nextNodes = parts[1].Split( + ',', + StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries + ); + var left = nextNodes[0].Trim('('); + var right = nextNodes[1].Trim(')'); + + return new Node(current, left, right); + } +} \ No newline at end of file