namespace AdventOfCodeLibrary._2022.Day_08 { internal struct Tree { internal int X; internal int Y; internal char Height; internal bool IsVisible; internal Tree(int x, int y, char height) { X = x; Y = y; Height = height; IsVisible = false; } } internal class TreeChecker { private Tree[][] treeGrid; private Tree[][] rotatedGrid; internal int VisibleTrees(string[] treeArray) { treeGrid = new Tree[treeArray.Length][]; rotatedGrid = new Tree[treeArray[0].Length][]; for (int verticalIndex = 0; verticalIndex < treeArray.Length; verticalIndex++) { bool firstVertial = true; for (int horizontalIndex = 0; horizontalIndex < treeArray[0].Length; horizontalIndex++) { if (firstVertial) { treeGrid[verticalIndex] = new Tree[treeArray[0].Length]; firstVertial = false; } if (verticalIndex == 0) { rotatedGrid[horizontalIndex] = new Tree[treeArray.Length]; } Tree tree = new Tree(verticalIndex, horizontalIndex, treeArray[verticalIndex][horizontalIndex]); //Console.WriteLine($"Adding Tree to [{verticalIndex}][{horizontalIndex}] and [{horizontalIndex}][{verticalIndex}]"); treeGrid[verticalIndex][horizontalIndex] = tree; rotatedGrid[horizontalIndex][verticalIndex] = tree; } } int visible = 0; // start from the top Tree[] currentHighest = treeGrid[0]; // from top to bottom for (int treeIndex = 1; treeIndex < treeArray.Length - 2; treeIndex++) { int tmp = CheckVisibleTrees(ref currentHighest, treeGrid[treeIndex]); visible += tmp; } currentHighest = treeGrid[^1]; // from bottom to top for (int treeIndex = treeArray.Length - 1; treeIndex > 1 ; treeIndex--) { int tmp = CheckVisibleTrees(ref currentHighest, treeGrid[treeIndex]); visible += tmp; } currentHighest = rotatedGrid[0]; // from top to bottom with the rotated array for (int treeIndex = rotatedGrid.Length - 1; treeIndex > 1; treeIndex--) { int tmp = CheckVisibleTrees(ref currentHighest, rotatedGrid[treeIndex]); visible += tmp; } currentHighest = rotatedGrid[^1]; // from bottom to top with the rotated array for (int treeIndex = rotatedGrid.Length - 1; treeIndex > 1; treeIndex--) { int tmp = CheckVisibleTrees(ref currentHighest, rotatedGrid[treeIndex]); visible += tmp; } // add the outside trees int edgeTrees = (2 * treeGrid.Length) + (2 * (treeGrid[0].Length - 2)); // return the result return visible + edgeTrees; } private int CheckVisibleTrees(ref Tree[] currentHighest, Tree[] treeLineToCheck) { int visible = 0; for (int treeIndex = 1; treeIndex < treeLineToCheck.Length - 1; treeIndex++) { Tree toCheck = treeLineToCheck[treeIndex]; int diff = toCheck.Height - currentHighest[treeIndex].Height; if (diff > 0 && !treeGrid[toCheck.X][toCheck.Y].IsVisible) { visible++; treeGrid[toCheck.X][toCheck.Y].IsVisible = true; currentHighest[treeIndex] = treeLineToCheck[treeIndex]; } } return visible; } } }