var rawTopographicMap = File.ReadLines("input.txt"); var topographicMap = CreateTopographicMap(rawTopographicMap); var availableDirections = new List<(int, int)>() { (-1, 0), // Up (1, 0), // Down (0, -1), // Left (0, 1) // Right }; Console.WriteLine($"Part1: {Part1(topographicMap, availableDirections)}\nPart2: {Part2(topographicMap, availableDirections)}"); int Part2(int[,] mapInput, List<(int, int)> directions) { var totalRating = 0; for (var r = 0; r < mapInput.GetLength(0); r++) { for (var c = 0; c < mapInput.GetLength(1); c++) { if (mapInput[r, c] == 0) { totalRating += FindDistinctTrails(r, c, mapInput, directions); } } } return totalRating; } // Could reuse the trailHead method with minor edits int FindDistinctTrails(int r, int c, int[,] mapInput, List<(int, int)> directions) { var stack = new Stack>(); stack.Push(new List<(int, int)> { (r, c) }); var trails = 0; while (stack.Count > 0) { var currentPath = stack.Pop(); var (cr, cc) = currentPath[^1]; if (mapInput[cr, cc] == 9) { trails++; continue; } foreach (var (dr, dc) in directions) { var nr = cr + dr; var nc = cc + dc; if (nr >= 0 && nr < mapInput.GetLength(0) && nc >= 0 && nc < mapInput.GetLength(1) && mapInput[nr, nc] == mapInput[cr, cc] + 1) { var nextPath = new List<(int, int)>(currentPath); nextPath.Add((nr, nc)); stack.Push(nextPath); } } } return trails; } int Part1(int[,] map, List<(int, int)> directions) { var totalScore = 0; for (var row = 0; row < map.GetLength(0); row++) { for (var column = 0; column < map.GetLength(1); column++) { if (map[row, column] == 0) { totalScore += TrailHead(row, column, map, directions); } } } return totalScore; } int TrailHead(int startRow, int startColumn, int[,] map, List<(int, int)> directions) { var rows = map.GetLength(0); var cols = map.GetLength(1); var queue = new Queue<(int, int)>(); var visited = new HashSet<(int, int)>(); var reachableNines = new HashSet<(int, int)>(); queue.Enqueue((startRow, startColumn)); while (queue.Count > 0) { var (r, c) = queue.Dequeue(); if (visited.Contains((r, c))) continue; visited.Add((r, c)); if (map[r, c] == 9) { reachableNines.Add((r, c)); continue; } foreach (var dir in directions) { var nr = r + dir.Item1; var nc = c + dir.Item2; if (nr >= 0 && nr < rows && nc >= 0 && nc < cols) { if (map[nr, nc] == map[r, c] + 1) { queue.Enqueue((nr, nc)); } } } } return reachableNines.Count; } int[,] CreateTopographicMap(IEnumerable lines) { var lineList = lines.Select(line => line.Trim()).ToList(); var map = new int[lineList.Count, lineList[0].Length]; for (var r = 0; r < map.GetLength(0); r++) { for (var c = 0; c < map.GetLength(1); c++) { map[r, c] = lineList[r][c] - '0'; } } return map; }