// See https://aka.ms/new-console-template for more information using System.Collections; var exampleData = new LoadedData("example-input.txt"); var puzzleData = new LoadedData("puzzle-input.txt"); exampleData.Print(); Console.WriteLine(String.Format("Part01, visibility: Example({0}), Puzzle({1})", exampleData.VisibleCount, puzzleData.VisibleCount)); Console.WriteLine(String.Format("Part01, Scenic Score: Example({0}), Puzzle({1})", exampleData.ScenicScore, puzzleData.ScenicScore)); class LoadedData { public List> TreeData { get; } = new List>(); public void Print() { string toPrint = ""; for (int j = 0; j < TreeData.Count; j++) { for (int i = 0; i < TreeData[j].Count; i++) { toPrint += TreeData[j][i]; } toPrint += "\n"; } Console.WriteLine(toPrint); } public LoadedData(string fileName) { TreeData = new List>(); using (StreamReader reader = System.IO.File.OpenText(fileName)) { while (!reader.EndOfStream) { string? line = reader.ReadLine(); if (line == null) { throw new InvalidDataException(); } List list = new List(); foreach (char c in line) { list.Add((int)(c - '0')); } TreeData.Add(list); } } } public int VisibleCount { get { int visible = 0; // Check the inside for (int j = 1; j < TreeData.Count-1; j++) { for (int i = 1; i < TreeData[0].Count-1; i++) { if (IsVisible(i,j)) { visible++; } } } // Add the top row and bottom row visible += TreeData[0].Count * 2; // Add the two sides visible += (TreeData.Count-2)*2; return visible; } } private bool IsVisible(int i, int j) { int baseHeight = TreeData[j][i]; bool visUp = true, visRight = true, visLeft = true, visDown = true; // Up for (int y = 0, x=i; y < j; y++) { if (baseHeight <= TreeData[y][x]) { visUp = false; break; } } if (visUp) return true; // Right for (int x = i+1, y=j; x < TreeData[i].Count; x++) { if (baseHeight <= TreeData[y][x]) { visRight = false; break; } } if (visRight) return true; // Left for (int x = 0, y = j; x < i; x++) { if (baseHeight <= TreeData[y][x]) { visLeft = false; break; } } if (visLeft) return true; // Down for (int y = j+1, x = i; y < TreeData.Count; y++) { if (baseHeight <= TreeData[y][x]) { visDown = false; break; } } if (visDown) return true; return false; } public int ScenicScore { get { int result = 0; for (int j = 1; j < TreeData.Count - 1; j++) { for (int i = 1; i < TreeData[0].Count - 1; i++) { result = Int32.Max(result, GetScenicScore(i, j)); } } return result; } } private int GetScenicScore(int i, int j) { int baseHeight = TreeData[j][i]; int viewUp=0, viewDown=0, viewLeft=0, viewRight=0; // Up for (int y = j-1, x = i; y >= 0; y--) { viewUp++; if (TreeData[y][x] >= baseHeight) { break; } } // Right for (int x = i + 1, y = j; x < TreeData[i].Count; x++) { viewRight++; if (TreeData[y][x] >= baseHeight) { break; } } // Left for (int x = i-1, y = j; x >= 0; x--) { viewLeft++; if (TreeData[y][x] >= baseHeight) { break; } } // Down for (int y = j + 1, x = i; y < TreeData.Count; y++) { viewDown++; if (TreeData[y][x] >= baseHeight) { break; } } return viewUp * viewDown * viewLeft * viewRight; } }