diff --git a/2022/README.md b/2022/README.md index de75d511cbfa258c10c9c54381fadfd32c8e3139..6d1f3b647376bb810dbbeb6e4d7bac6bd0d89d58 100644 --- a/2022/README.md +++ b/2022/README.md @@ -218,5 +218,17 @@ it will serve both parts. ## Day 8 +### Part 1 + +The subproblems are +- Determine whether a tree is visible + - From the right or left + - From the top or bottom (solution space -- this may be easier if I add a subproblem of rotating the matrix) +- Count the number of visible trees + +### Part 2 + +## Day 9 + (coming soon) diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day8.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day8.java new file mode 100644 index 0000000000000000000000000000000000000000..ef732038718f39c1a6e3bb65d9f826042c7cfe80 --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day8.java @@ -0,0 +1,87 @@ +package edu.unl.cse.bohn.year2022; + +import edu.unl.cse.bohn.Puzzle; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +@SuppressWarnings("unused") +public class Day8 extends Puzzle { + public Day8(boolean isProductionReady) { + super(isProductionReady); + sampleData = """ + 30373 + 25512 + 65332 + 33549 + 35390"""; + } + + @Override + public long computePart1(List<String> data) { + boolean[][] visibleTrees = computeTreeVisibility(data); + long numberOfVisibleTrees = 0; + for (boolean[] row : visibleTrees) { + numberOfVisibleTrees += IntStream.range(0, row.length).map(i -> row[i] ? 1 : 0).sum(); + } + return numberOfVisibleTrees; + } + + @Override + public long computePart2(List<String> data) { + return 0; + } + + private boolean[][] computeTreeVisibility(List<String> data) { + // Initially assume each tree is not visible; if it is the tallest tree from any direction, it is visible. + boolean[][] visibleTrees = new boolean[data.size()][data.get(0).length()]; + // Put the tree heights in a form that will be easy to use and manipulate. + int[][] treeHeights = new int[data.size()][data.get(0).length()]; + for (int i = 0; i < visibleTrees.length; i++) { + Arrays.fill(visibleTrees[i], false); + treeHeights[i] = data.get(i).chars().map(c -> c - '0').toArray(); + } + int[][] rotatedTreeHeights = flipMatrixAlongDiagonal(treeHeights); + // Is each tree visible from left or right? + for (int i = 0; i < visibleTrees.length; i++) { + List<Integer> row = Arrays.stream(treeHeights[i]).boxed().toList(); + for (int j = 0; j < visibleTrees[i].length; j++) { + if (j == 0 || j == visibleTrees[i].length - 1) { + visibleTrees[i][j] = true; + } else { + visibleTrees[i][j] = visibleTrees[i][j] + || (treeHeights[i][j] > row.subList(0, j).stream().max(Integer::compareTo).orElseThrow()) + || (treeHeights[i][j] > row.subList(j + 1, + treeHeights[i].length).stream().max(Integer::compareTo).orElseThrow()); + } + } + } + // Is each tree visible from top or bottom? + for (int j = 0; j < visibleTrees[0].length; j++) { + List<Integer> column = Arrays.stream(rotatedTreeHeights[j]).boxed().toList(); + for (int i = 0; i < visibleTrees.length; i++) { + if (i == 0 || i == visibleTrees.length - 1) { + visibleTrees[i][j] = true; + } else { + visibleTrees[i][j] = visibleTrees[i][j] + || (rotatedTreeHeights[j][i] > column.subList(0, i).stream() + .max(Integer::compareTo).orElseThrow()) + || (rotatedTreeHeights[j][i] > column.subList(i + 1, treeHeights.length).stream() + .max(Integer::compareTo).orElseThrow()); + } + } + } + return visibleTrees; + } + + private int[][] flipMatrixAlongDiagonal(int[][] matrix) { + int[][] rotatedMatrix = new int[matrix[0].length][matrix.length]; + for (int i = 0; i < rotatedMatrix.length; i++) { + for (int j = 0; j < rotatedMatrix[i].length; j++) { + rotatedMatrix[i][j] = matrix[j][i]; + } + } + return rotatedMatrix; + } +}