diff --git a/AoC_2025.Tests/Day07Test.cs b/AoC_2025.Tests/Day07Test.cs new file mode 100644 index 0000000..0e42824 --- /dev/null +++ b/AoC_2025.Tests/Day07Test.cs @@ -0,0 +1,47 @@ +using AdvenOfCode.Contracts; + +namespace AoC_2025.Tests; + +public class Day07Test +{ + private readonly IPuzzleSolver _sut; + private static readonly string rootPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + private readonly string TestInputPath = @$"{rootPath}\AoC-PuzzleInputs\2025\Test\day07.txt"; + private readonly string ProdInputPath = @$"{rootPath}\AoC-PuzzleInputs\2025\Prod\day07.txt"; + + public Day07Test() + { + _sut = new Day07(); + } + [Fact] + public void Part01_Test_equals_21() + { + var actual = _sut.SolvePart1(TestInputPath); + + Assert.Equal(21, actual); + } + + [Fact] + public void Part01_Prod_equals_1658() + { + var actual = _sut.SolvePart1(ProdInputPath); + + Assert.Equal(1658, actual); + } + + [Fact] + public void Part02_Test_equals_40() + { + var actual = _sut.SolvePart2(TestInputPath); + + Assert.Equal(40, actual); + } + + [Fact] + public void Part02_Prod_equals_53916299384254() + { + var actual = _sut.SolvePart2(ProdInputPath); + + Assert.Equal(53916299384254, actual); + } +} \ No newline at end of file diff --git a/AoC_2025/Day07.cs b/AoC_2025/Day07.cs new file mode 100644 index 0000000..5d20e9d --- /dev/null +++ b/AoC_2025/Day07.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Data.Common; +using System.IO; +using System.Linq; +using AdvenOfCode.Contracts; +using Coordinate = (int x, int y); + +namespace AoC_2025; + +public class Day07 : IPuzzleSolver +{ + private string[] ParsePuzzleInput(string path) + { + var puzzleInput = File.ReadAllLines(path) + .Where(line => !string.IsNullOrWhiteSpace(line)) + .ToArray(); + return puzzleInput; + } + + public long SolvePart1(string pathToPuzzleInput) + { + var grid = ParsePuzzleInput(pathToPuzzleInput); + var start = GetStart(grid); + var count = TraverseGridAndCountSplitters(grid, start); + return count; + } + + public long SolvePart2(string pathToPuzzleInput) + { + var grid = ParsePuzzleInput(pathToPuzzleInput); + var start = GetStart(grid); + var count = GetNodesTraversedWitTimelineCount(grid, start, [], []); + return count[start]; + } + + private Coordinate GetStart(string[] grid) + { + return (0, grid[0].IndexOf('S')); + } + + private long TraverseGridAndCountSplitters(string[] grid, Coordinate start) + { + HashSet visited = [start]; + var seen = new Queue(); + seen.Enqueue(start); + var splittersHit = 0L; + while (seen.TryDequeue(out var current)) + { + if (current.x >= grid.Length) continue; + if (current.y >= grid[0].Length || current.y < 0) continue; + + if (grid[current.x][current.y] == '^') + { + splittersHit++; + var nextLeft = (current.x, current.y - 1); + var nextRight = (current.x, current.y + 1); + if (visited.Add(nextLeft)) seen.Enqueue(nextLeft); + if (visited.Add(nextRight)) seen.Enqueue(nextRight); + } + else + { + var next = (current.x + 1, current.y); + if (visited.Add(next)) seen.Enqueue(next); + } + } + + return splittersHit; + } + + private Dictionary GetNodesTraversedWitTimelineCount(string[] grid, Coordinate current, HashSet path, Dictionary nodeCountVisited) + { + if (current.x >= grid.Length || nodeCountVisited.ContainsKey(current)) + { + var addAmount = nodeCountVisited.GetValueOrDefault(current, 1); + foreach (var node in path) + { + nodeCountVisited[node] += addAmount; + } + + return nodeCountVisited; + } + + nodeCountVisited[current] = 0; + path.Add(current); + + if (grid[current.x][current.y] == '^') + { + var resLeft = GetNodesTraversedWitTimelineCount(grid, (current.x, current.y - 1), [..path], nodeCountVisited); + var resRight = GetNodesTraversedWitTimelineCount(grid, (current.x, current.y + 1), [..path], resLeft); + return resRight; + } + else + { + var res = GetNodesTraversedWitTimelineCount(grid, (current.x + 1, current.y), [..path], nodeCountVisited); + return res; + } + } +} \ No newline at end of file