Skip to content
Snippets Groups Projects
Commit 94dd084c authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Completed Year 2022 Day 8

parent 24f8ba86
No related branches found
No related tags found
No related merge requests found
......@@ -221,6 +221,7 @@ it will serve both parts.
### Part 1
The subproblems are
- Determine the tree heights
- 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)
......@@ -228,6 +229,24 @@ The subproblems are
### Part 2
The subproblems are
- Determine the tree heights
- Determine the scenic score for each tree
- For each tree, determine the distance, in each direction, to the next tree that is at least as tall
- Multiply those distances
- Report the greatest scenic score
### Refactoring
Extracted the code that generates a matrix of tree heights.
The structure between the code that computes tree visibility and the scenic score are essentially identical;
the not-inconsiderable difference is that one works on a boolean matrix, and the other works on an integer matrix.
I *suppose* I could make the boolean matrix be an integer matrix of 0s and 1s, but that would pain me almost as much as
the structural DRY issue.
So, just this once, I'm going to pinch my nose and accept the structural DRY issue.
Well... I'm going to take the part 2 code in a (very) slightly different direction than the part 1 code.
## Day 9
(coming soon)
......
......@@ -30,40 +30,45 @@ public class Day8 extends Puzzle {
@Override
public long computePart2(List<String> data) {
return 0;
int[][] scenicScores = computeScenicScores(data);
long maximumScenicScore = Long.MIN_VALUE;
for (int[] row : scenicScores) {
maximumScenicScore = Long.max(maximumScenicScore, Arrays.stream(row).max().orElseThrow());
}
return maximumScenicScore;
}
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.
private static int[][] getTreeHeights(List<String> data) {
int[][] treeHeights = new int[data.size()][data.get(0).length()];
for (int i = 0; i < visibleTrees.length; i++) {
Arrays.fill(visibleTrees[i], false);
for (int i = 0; i < treeHeights.length; i++) {
treeHeights[i] = data.get(i).chars().map(c -> c - '0').toArray();
}
return treeHeights;
}
private boolean[][] computeTreeVisibility(List<String> data) {
// Put the tree heights in a form that will be easy to use and manipulate.
int[][] treeHeights = getTreeHeights(data);
int[][] rotatedTreeHeights = flipMatrixAlongDiagonal(treeHeights);
// 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()];
for (boolean[] visibleTree : visibleTrees) {
Arrays.fill(visibleTree, false);
}
// 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) {
List<Integer> column = Arrays.stream(rotatedTreeHeights[j]).boxed().toList();
if (i == 0 || i == visibleTrees.length - 1) {
visibleTrees[i][j] = true;
} else 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())
......@@ -84,4 +89,51 @@ public class Day8 extends Puzzle {
}
return rotatedMatrix;
}
private int[][] computeScenicScores(List<String> data) {
int[][] treeHeights = getTreeHeights(data);
int[][] rotatedTreeHeights = flipMatrixAlongDiagonal(treeHeights);
int[][] scenicScores = new int[treeHeights.length][treeHeights[0].length];
for (int i = 0; i < scenicScores.length; i++) {
List<Integer> row = Arrays.stream(treeHeights[i]).boxed().toList();
for (int j = 0; j < scenicScores[i].length; j++) {
scenicScores[i][j] = computeScenicScoreAlongOneDimension(treeHeights, i, j,
true, scenicScores[i].length);
scenicScores[i][j] *= computeScenicScoreAlongOneDimension(treeHeights, i, j,
false, scenicScores.length);
}
}
return scenicScores;
}
private int computeScenicScoreAlongOneDimension(int[][] treeHeights, int i, int j,
boolean dimensionIsRow, int sizeOfDimension) {
int positionAlongDimension = dimensionIsRow ? j : i;
Integer nextFactor = positionAlongDimension;
int scenicScore = 1;
for (int k = 0; k < sizeOfDimension; k++) {
int possiblyBlockingTreeHeight = dimensionIsRow ? treeHeights[i][k] : treeHeights[k][j];
if (positionAlongDimension > k) { // above or to the left
if (possiblyBlockingTreeHeight >= treeHeights[i][j]) {
nextFactor = positionAlongDimension - k;
}
} else if (positionAlongDimension == k) {
//noinspection DataFlowIssue
scenicScore *= nextFactor;
} else { // below or to the right
if (nextFactor != null) {
if (possiblyBlockingTreeHeight >= treeHeights[i][j]) {
nextFactor = k - positionAlongDimension;
scenicScore *= nextFactor;
nextFactor = null;
}
}
}
}
if (nextFactor != null) {
nextFactor = sizeOfDimension - positionAlongDimension - 1;
scenicScore *= nextFactor;
}
return scenicScore;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment