github.com/cycloss/advent-of-code@v0.0.0-20221210145555-15039b95faa6/2022/lib/day8.dart (about) 1 import 'dart:io'; 2 3 import 'package:2022/wrapped_primitives.dart'; 4 5 class Tree { 6 final int height; 7 bool visible; 8 Tree(this.height, this.visible); 9 List<int> scenicScores = []; 10 int get totalScenicScore { 11 var scoreTotal = 1; 12 for (var score in scenicScores) { 13 scoreTotal *= score; 14 } 15 return scoreTotal; 16 } 17 } 18 19 void day8() { 20 var lines = File('inputs/day8').readAsLinesSync(); 21 var grid = generateGrid(lines); 22 // tree heights 0 to 9 (0 is a tree) 23 // tree visible if all trees from it to edge are shorter than it 24 // plan is to start at level 9 and go down to 0 25 // do each row forward and back, and each column up and down 26 // start all tuples as visible null 27 // possibly unnecessary: if index of iteration is 0 (an edge), set visible to true 28 // if a visible tree is found before tree of current level, stop and move to next (lower) level as that tree is taller and so nothing after will be visible for the current level 29 // if a tree of the current height is found, set it to visible, and all trees after to invisible, until you get to a tree that is visible (will be higher than it, set on a previous iteration) 30 31 findVisibleTrees(grid); 32 // printGrid(grid); 33 print("Part 1:"); 34 countVisibleTrees(grid); 35 36 findScenicScores(grid); 37 38 print("Part 2:"); 39 findMaxScenicScore(grid); 40 } 41 42 void countVisibleTrees(List<List<Tree>> grid) { 43 var total = 0; 44 for (var row in grid) { 45 for (var tree in row) { 46 if (tree.visible) { 47 total++; 48 } 49 } 50 } 51 print(total); 52 } 53 54 void findMaxScenicScore(List<List<Tree>> grid) { 55 var max = 0; 56 for (var row in grid) { 57 for (var tree in row) { 58 if (tree.totalScenicScore > max) { 59 max = tree.totalScenicScore; 60 } 61 } 62 } 63 print(max); 64 } 65 66 void printGrid(List<List<Tree>> grid) { 67 for (var row in grid) { 68 for (var tree in row) { 69 stdout.write('${tree.visible} '); 70 } 71 print(""); 72 } 73 } 74 75 void findVisibleTrees(List<List<Tree>> grid) { 76 for (var currentLevel = 9; currentLevel >= 0; currentLevel--) { 77 for (var row in grid) { 78 // iterate row forward for current level 79 processVisibilityOfLine(row, currentLevel); 80 // iterate row backward for current level 81 processVisibilityOfLine(row.reversed, currentLevel); 82 } 83 for (var column in getGridColumns(grid)) { 84 // iterate row forward for current level 85 processVisibilityOfLine(column, currentLevel); 86 // iterate row backward for current level 87 processVisibilityOfLine(column.reversed, currentLevel); 88 } 89 } 90 } 91 92 List<List<Tree>> getGridColumns(List<List<Tree>> grid) { 93 var columns = <List<Tree>>[]; 94 for (var i = 0; i < grid[0].length; i++) { 95 var column = <Tree>[]; 96 for (var j = 0; j < grid.length; j++) { 97 column.add(grid[j][i]); 98 } 99 columns.add(column); 100 } 101 return columns; 102 } 103 104 void processVisibilityOfLine(Iterable<Tree> line, int currentLevel) { 105 var found = Bool(false); 106 for (var tree in line) { 107 if (tree.visible) { 108 // break as found a tree taller of the same size before found tree of current height 109 break; 110 } 111 processTreeVisibility(tree, found, currentLevel); 112 } 113 } 114 115 void processTreeVisibility(Tree tree, Bool found, int currentLevel) { 116 if (found.b) { 117 // tree must be smaller and therefore not visible as not encountered large visible tree yet, and tree of current level found 118 tree.visible = false; 119 return; 120 } 121 if (tree.height == currentLevel) { 122 tree.visible = true; 123 found.b = true; 124 } 125 } 126 127 void findScenicScores(List<List<Tree>> grid) { 128 for (var currentLevel = 9; currentLevel >= 0; currentLevel--) { 129 for (var row in grid) { 130 // iterate row forward for current level 131 processScenicScoreOfLine(row, currentLevel); 132 // iterate row backward for current level 133 processScenicScoreOfLine(row.reversed, currentLevel); 134 } 135 for (var column in getGridColumns(grid)) { 136 // iterate row forward for current level 137 processScenicScoreOfLine(column, currentLevel); 138 // iterate row backward for current level 139 processScenicScoreOfLine(column.reversed, currentLevel); 140 } 141 } 142 } 143 144 void processScenicScoreOfLine(Iterable<Tree> line, int currentLevel) { 145 // set score to 0 as no trees on edge 146 var score = 0; 147 for (var tree in line) { 148 if (tree.height >= currentLevel) { 149 if (tree.height == currentLevel) { 150 tree.scenicScores.add(score); 151 } 152 // set score to one as current tree counts 153 score = 1; 154 } else { 155 score++; 156 } 157 } 158 } 159 160 List<List<Tree>> generateGrid(List<String> lines) { 161 var grid = <List<Tree>>[]; 162 for (var line in lines) { 163 var gridLine = <Tree>[]; 164 for (var char in line.split("")) { 165 gridLine.add(Tree(int.parse(char), false)); 166 } 167 grid.add(gridLine); 168 } 169 return grid; 170 }