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

Completed 2022 Day 18

parent 644f2198
No related branches found
No related tags found
No related merge requests found
......@@ -654,9 +654,39 @@ No. That solves the memory problem but not the time problem.
Even if we could process 4 billion rocks per second (which we can't) then it would take a little over 4 minutes to
process 1 trillion rocks, and AOC solutions shouldn't take that long.
There is almost certainly a cycle (with a period that is a multiple of both the number of rocks and the length of the
jet string?) -- if we can detect the cycle then we can determine the height as (height of prefix) +
(number of cycles) * (height of a cycle) + (height of suffix). Maybe later.
...
## Day 18
- [The problem](https://adventofcode.com/2022/day/18)
- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day18.java)
### Part 1
The subproblems are
- Parse the input to determine where each cube is in space
- For each cube, determine which faces are adjacent to another cube
- Count the number of faces that are not adjacent to another cube
Determining whether a face is adjacent to another cube should be straight-forward.
Given axes *i*, *j*, and *k*, cube *c1* is adjacent to cube *c2* iff wlog *c1.i* = *c2.i* and *c1.j* = *c2.j* and
*c1.k* = *c2.k* ± 1.
### Part 2
We need to determine how many cavities are present in the droplet.
We can determine that by eliminating everything that is *not* a cavity.
If we consider a bounding box, then every cube is either:
- Lava, as computed in part 1
- Exterior air, which has no lava between it and the box's bound in at least one direction
- A cavity
## Day 19
(coming soon)
package edu.unl.cse.bohn.year2022;
import edu.unl.cse.bohn.Puzzle;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;
@SuppressWarnings("unused")
public class Day18 extends Puzzle {
@SuppressWarnings("CommentedOutCode")
public Day18(boolean isProductionReady) {
super(isProductionReady);
// sampleData = """
// 1,1,1
// 2,1,1""";
sampleData = """
2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5""";
}
@Override
public long computePart1(List<String> data) {
for (String description : data) {
new Cube(description);
}
for (Cube cube1 : Cube.lava) {
for (Cube cube2 : Cube.lava) {
cube1.checkIfAdjacentTo(cube2);
}
}
return Cube.lava.stream().mapToLong(Cube::countExposedFaces).sum();
}
@Override
public long computePart2(List<String> data) {
// assume (correctly) that lava has already been created
int upperBound = Cube.maximumLength + 2; // plenty
for (int i = 0; i < upperBound; i++) {
for (int j = 0; j < upperBound; j++) {
for (int k = 0; k < upperBound; k++) {
new Cube(i, j, k);
}
}
}
Cube.removeExteriorAir();
for (Cube lavaCube : Cube.lava) {
for (Cube airCube : Cube.air) {
lavaCube.checkIfAdjacentTo(airCube);
}
}
return Cube.lava.stream().mapToLong(Cube::countExposedFaces).sum();
}
private static class Cube {
public static final Set<Cube> lava = new HashSet<>();
public static final Set<Cube> air = new HashSet<>();
static int maximumLength = Integer.MIN_VALUE;
private final int[] coordinates;
private final boolean[] faceIsExposed;
public Cube(String lavaDescription) {
// use for lava
coordinates = Arrays.stream(lavaDescription.split(",")).mapToInt(Integer::parseInt).toArray();
faceIsExposed = new boolean[]{true, true, true, true, true, true};
maximumLength = Math.max(maximumLength, Arrays.stream(coordinates).max().orElseThrow());
air.remove(this);
lava.add(this);
}
public Cube(int x, int y, int z) {
// use for air
coordinates = new int[]{x, y, z};
faceIsExposed = new boolean[]{true, true, true, true, true, true};
if (!lava.contains(this)) {
air.add(this);
}
}
public static void removeExteriorAir() {
Set<Cube> exteriorAir = new HashSet<>();
for (Cube airCube : air) {
for (Cube lavaCube : lava) {
if (airCube.isAlignedInTwoDimensionsWith(lavaCube, 1, 2)
&& airCube.distanceInOneDimension(lavaCube, 0) != 0) {
airCube.faceIsExposed[airCube.distanceInOneDimension(lavaCube, 0) < 0 ? 0 : 1] = false;
}
if (airCube.isAlignedInTwoDimensionsWith(lavaCube, 0, 2)
&& airCube.distanceInOneDimension(lavaCube, 1) != 0) {
airCube.faceIsExposed[2 + (airCube.distanceInOneDimension(lavaCube, 1) < 0 ? 0 : 1)] = false;
}
if (airCube.isAlignedInTwoDimensionsWith(lavaCube, 0, 1)
&& airCube.distanceInOneDimension(lavaCube, 2) != 0) {
airCube.faceIsExposed[4 + (airCube.distanceInOneDimension(lavaCube, 2) < 0 ? 0 : 1)] = false;
}
}
if (airCube.countExposedFaces() > 0) {
exteriorAir.add(airCube);
}
}
air.removeAll(exteriorAir);
// if we stopped now, then air in twisty passages would be treated as cavities
// any air that is adjacent to exterior air must also be exterior air
Set<Cube> newlyDiscoveredExteriorAir;
do {
newlyDiscoveredExteriorAir = new HashSet<>();
for (Cube cavityCube : air) {
for (Cube exteriorCube : exteriorAir) {
if (cavityCube.checkIfAdjacentTo(exteriorCube)) {
newlyDiscoveredExteriorAir.add(cavityCube);
}
}
}
exteriorAir.addAll(newlyDiscoveredExteriorAir);
air.removeAll(newlyDiscoveredExteriorAir);
} while (!newlyDiscoveredExteriorAir.isEmpty());
}
private int distanceInOneDimension(Cube other, int dimension) {
return other.coordinates[dimension] - this.coordinates[dimension];
}
private boolean isAlignedInTwoDimensionsWith(Cube other, int dimension1, int dimension2) {
return distanceInOneDimension(other, dimension1) == 0 && distanceInOneDimension(other, dimension2) == 0;
}
@SuppressWarnings("UnusedReturnValue")
private boolean checkIfAdjacentTo(Cube other) {
if (isAlignedInTwoDimensionsWith(other, 1, 2)
&& Math.abs(distanceInOneDimension(other, 0)) == 1) {
faceIsExposed[(1 + distanceInOneDimension(other, 0)) / 2] = false;
return true;
}
if (isAlignedInTwoDimensionsWith(other, 0, 2)
&& Math.abs(distanceInOneDimension(other, 1)) == 1) {
faceIsExposed[2 + (1 + distanceInOneDimension(other, 1)) / 2] = false;
return true;
}
if (isAlignedInTwoDimensionsWith(other, 0, 1)
&& Math.abs(distanceInOneDimension(other, 2)) == 1) {
faceIsExposed[4 + (1 + distanceInOneDimension(other, 2)) / 2] = false;
return true;
}
return false;
}
private long countExposedFaces() {
return IntStream.range(0, faceIsExposed.length).filter(i -> faceIsExposed[i]).count();
}
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (!(other instanceof Cube cube)) return false;
return Arrays.equals(coordinates, cube.coordinates);
}
@Override
public int hashCode() {
return Arrays.hashCode(coordinates);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment