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

Day 9 complete

parent 6e55cf34
No related branches found
No related tags found
No related merge requests found
...@@ -56,7 +56,7 @@ Part 2 looks a bit more interesting. We *could* go for an ...@@ -56,7 +56,7 @@ Part 2 looks a bit more interesting. We *could* go for an
O(num_crabs * max_distance^2) solution, or we could recognize what Euler O(num_crabs * max_distance^2) solution, or we could recognize what Euler
recognized: ∑_{i=1}^{n}i = n(n+1)/2. recognized: ∑_{i=1}^{n}i = n(n+1)/2.
### Day 8 ## Day 8
Seven-segment displays are cool. This has the potential to be a pain. Part 1 Seven-segment displays are cool. This has the potential to be a pain. Part 1
looks okay -- examining only the output patterns, count the number of patterns looks okay -- examining only the output patterns, count the number of patterns
...@@ -85,3 +85,32 @@ explanation, I'm going to use numerals to depict the sets of illuminated segment ...@@ -85,3 +85,32 @@ explanation, I'm going to use numerals to depict the sets of illuminated segment
It turns out we can ascertain the digits without needing to record the segments. It turns out we can ascertain the digits without needing to record the segments.
That's nifty. That's nifty.
## Day 9
Part 1 doesn't look too fancy I'll simplify the adjacency-check a little by
making the heightmap larger by two in each dimension so that I can create a
"frame" of `MAX_VALUE`s.
Hmmm -- While that O(num_rows * num_columns) algorithm took a fraction of a
second, it was noticeable on the human scale. I don't think there's a better
big-O approach, but the constant factors could be in play if I were to look
for optimizations.
Part 2 defines "basin" okay, but requires a little thought to express as
numbers. In the examples, the basins seem to be monotonic until reaching
height 9. Monotonic makes sense, given the definition "...flow downward to a
single low point," but what about a location of height 6 that has a basin on
either side?
- I'm going to assume, for now, that there are locations whose height is less
than 9 that are between two basins -- the simple check to see if there's an
adjacent location of greater height potentially could count a location as
being in two locations otherwise. If I'm wrong, I'll fix it.
- Come to think of it, plateaus would also be a problem for the simple
check. The examples don't have any plateaus.
- I'm going to change my part 1 code to create a height-9 frame. That's
enough for the low-point calculation and will simply part 2 a little. I'm
also going to change my part 1 code to record the low points so that I
don't have to re-calculate them for part 2.
- We'll go for a finite element approach.
Hmm. Part 2 takes a few seconds, but no surprise there -- it's now O(n^5).
package edu.unl.cse.bohn.year2021;
import edu.unl.cse.bohn.Puzzle;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@SuppressWarnings("unused")
public class Day9 extends Puzzle {
public record Point(int x, int y) {
}
private long[][] heightmap;
private boolean[][] lowPoints;
public Day9(boolean isProductionReady) {
super(isProductionReady);
sampleData = """
2199943210
3987894921
9856789892
8767896789
9899965678""";
}
@Override
public long computePart1(List<String> data) {
heightmap = new long[data.size() + 2][data.get(0).length() + 2];
lowPoints = new boolean[data.size() + 2][data.get(0).length() + 2];
for (long[] row : heightmap) {
Arrays.fill(row, 9L);
}
for (boolean[] row : lowPoints) {
Arrays.fill(row, false);
}
for (int i = 0; i < data.size(); i++) {
String line = data.get(i);
for (int j = 0; j < line.length(); j++) {
heightmap[i + 1][j + 1] = Long.parseLong(String.valueOf(line.charAt(j)));
}
}
long riskTotal = 0L;
for (int i = 1; i < heightmap.length - 1; i++) {
for (int j = 1; j < heightmap[i].length - 1; j++) {
long height = heightmap[i][j];
boolean isLowPoint = height < heightmap[i - 1][j] &&
height < heightmap[i + 1][j] &&
height < heightmap[i][j - 1] &&
height < heightmap[i][j + 1];
long risk = height + 1;
if (isLowPoint) {
lowPoints[i][j] = true;
riskTotal += risk;
}
}
}
return riskTotal;
}
@Override
public long computePart2(List<String> data) {
List<Integer> basinSizes = new LinkedList<>();
for (int i = 0; i < heightmap.length; i++) {
for (int j = 0; j < heightmap[i].length; j++) {
if (lowPoints[i][j]) {
Set<Point> basinPoints = new HashSet<>();
basinPoints.add(new Point(i, j));
boolean newPointsAdded = true;
while (newPointsAdded) {
newPointsAdded = false;
for (int m = 0; m < heightmap.length; m++) {
for (int n = 0; n < heightmap[m].length; n++) {
long height = heightmap[m][n];
Point point = new Point(m, n);
if (!basinPoints.contains(point) && height < 9) {
for (Point neighbor : Set.of(new Point(m - 1, n), new Point(m + 1, n),
new Point(m, n - 1), new Point(m, n + 1))) {
if (basinPoints.contains(neighbor) &&
height > heightmap[neighbor.x()][neighbor.y()]) {
basinPoints.add(point);
newPointsAdded = true;
}
}
}
}
}
}
basinSizes.add(basinPoints.size());
}
}
}
basinSizes.sort(null);
int numberOfBasins = basinSizes.size();
return (long)basinSizes.get(numberOfBasins - 1) *
(long)basinSizes.get(numberOfBasins - 2) *
(long)basinSizes.get(numberOfBasins - 3);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment