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

Day 15 part 1 complete

parent f224a445
No related branches found
No related tags found
No related merge requests found
......@@ -580,6 +580,15 @@ The subproblems are
- Determine which positions cannot contain a beacon (*i.e.*, which positions are no closer to the sensor
than the beacon)
Creating many, many beacons would seem to be untenable from a memory perspective.
I think we're going to have to dynamically build the map and then forget which sensor detected which beacon.
This is going to be a PITA Linked List of Linked Lists.
*Or*, I could make two passes, one to determine the matrix's dimensions, and one to populate it.
Okay, the problem (unsurprisingly) wasn't all the Sensor data; it was the 6,862,736 x 6,004,906 matrix.
What? You don't have several terabytes just lying around?
Clearly we need to go *back* to tracking the Sensor data and dynamically determine whether a given position is covered.
### Part 2
...
......
......@@ -2,13 +2,12 @@ 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")
@SuppressWarnings({"unused"})
public class Day15 extends Puzzle {
public Day15(boolean isProductionReady) {
super(isProductionReady);
......@@ -34,12 +33,8 @@ public class Day15 extends Puzzle {
for (String datum : data) {
new Sensor(datum);
}
Sensor.markPositionsAsHavingNoUnknownBeacon();
// Sensor.printMap();
// System.out.println("===");
//noinspection MagicNumber
return Sensor.countPositionsWithNoUnknownBeacon(isProductionReady ? 2000000 : 10);
// return 0;
return Sensor.countLocationsThatCannotHaveBeacon(isProductionReady ? 2000000 : 10);
}
@Override
......@@ -53,8 +48,11 @@ public class Day15 extends Puzzle {
private static final Set<Sensor> sensors = new HashSet<>();
private static boolean[][] mightContainAnUnknownBeacon = null;
private static int xOffset, yOffset;
// private static boolean[][] mightContainAnUnknownBeacon = null;
private static int minimumX = Integer.MAX_VALUE;
private static int maximumX = Integer.MIN_VALUE;
private static int minimumY = Integer.MAX_VALUE;
private static int maximumY = Integer.MIN_VALUE;
public Sensor(String description) {
String[] hardwareDescriptions = description.split(":");
......@@ -67,6 +65,11 @@ public class Day15 extends Puzzle {
nearestBeaconY =
Integer.parseInt(coordinateDescriptions[1].substring(coordinateDescriptions[1].indexOf('=') + 1));
sensors.add(this);
int distance = computeManhattanDistance(x, y, nearestBeaconX, nearestBeaconY);
minimumX = Math.min(minimumX, x - distance);
minimumY = Math.min(minimumY, y - distance);
maximumX = Math.max(maximumX, x + distance);
maximumY = Math.max(maximumY, y + distance);
}
public int getDistanceToBeacon() {
......@@ -74,7 +77,7 @@ public class Day15 extends Puzzle {
}
private int getDistanceToLocation(int x, int y) {
return Math.abs(x - this.x) + Math.abs(y - this.y);
return computeManhattanDistance(this.x, this.y, x, y);
}
public boolean isNoFartherThanBeacon(int x, int y) {
......@@ -87,93 +90,37 @@ public class Day15 extends Puzzle {
+ ", y=" + nearestBeaconY + "\t(distance=" + getDistanceToBeacon() + ")";
}
public static int computeManhattanDistance(int x1, int y1, int x2, int y2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
public static Sensor getSensorAt(int x, int y) {
return sensors.stream().filter(s -> s.x == x && s.y == y).findFirst().orElse(null);
}
public static boolean aSensorIsAt(int x, int y) {
return sensors.stream().anyMatch(s -> s.x == x && s.y == y);
}
public static Sensor getSensorDetectingBeaconAt(int x, int y) {
return sensors.stream()
.filter(s -> s.nearestBeaconX == x && s.nearestBeaconY == y).findFirst().orElse(null);
}
public static void markPositionsAsHavingNoUnknownBeacon() {
// create the matrix
int maximumX = sensors.stream()
.mapToInt(sensor -> sensor.x + sensor.getDistanceToBeacon())
.max().orElse(Integer.MIN_VALUE);
int minimumX = sensors.stream()
.mapToInt(sensor -> sensor.x - sensor.getDistanceToBeacon())
.min().orElse(Integer.MAX_VALUE);
int maximumY = sensors.stream()
.mapToInt(sensor -> sensor.y + sensor.getDistanceToBeacon())
.max().orElse(Integer.MIN_VALUE);
int minimumY = sensors.stream()
.mapToInt(sensor -> sensor.y - sensor.getDistanceToBeacon())
.min().orElse(Integer.MAX_VALUE);
xOffset = minimumX;
yOffset = minimumY;
mightContainAnUnknownBeacon = new boolean[maximumY - yOffset + 1][maximumX - xOffset + 1];
IntStream.range(0, mightContainAnUnknownBeacon.length)
.forEach(i -> Arrays.fill(mightContainAnUnknownBeacon[i], true));
// make our deductions
for (int i = 0; i < mightContainAnUnknownBeacon.length; i++) {
for (int j = 0; j < mightContainAnUnknownBeacon[i].length; j++) {
int y = i + yOffset, x = j + xOffset;
for (Sensor sensor : sensors) {
if (sensor.isNoFartherThanBeacon(x, y)) {
mightContainAnUnknownBeacon[i][j] = false;
}
}
}
}
}
public static int countPositionsWithNoUnknownBeacon(int y) {
if (mightContainAnUnknownBeacon == null) {
markPositionsAsHavingNoUnknownBeacon();
}
// System.out.print(xOffset + " ");
int countOfObservedLocations = 0;
int countOfKnownBeacons = 0;
int i = y - yOffset;
boolean[] row = mightContainAnUnknownBeacon[i];
for (int j = 0; j < row.length; j++) {
int x = j + xOffset;
// System.out.print(row[j] ? '.' : "#");
countOfObservedLocations += row[j] ? 0 : 1;
countOfKnownBeacons += (getSensorDetectingBeaconAt(x,y) == null) ? 0 : 1;
}
// System.out.println(" " + (mightContainAnUnknownBeacon[y - yOffset].length - xOffset - 1));
return countOfObservedLocations - countOfKnownBeacons;
}
public static void printMap() {
if (mightContainAnUnknownBeacon == null) {
markPositionsAsHavingNoUnknownBeacon();
}
System.out.println("xOffset = " + xOffset + "\tyOffset = " + yOffset);
for (int i = 0; i < mightContainAnUnknownBeacon.length; i++) {
int y = i + yOffset;
for (int j = 0; j < mightContainAnUnknownBeacon[i].length; j++) {
int x = j + xOffset;
if (getSensorAt(x,y) != null) {
System.out.print("S");
} else if (getSensorDetectingBeaconAt(x,y) != null) {
System.out.print("B");
} else if (mightContainAnUnknownBeacon[i][j]) {
System.out.print(".");
} else {
System.out.print("#");
}
if (x % 5 == 4 || x == -1) {
System.out.print(" ");
}
}
System.out.println();
if (y % 5 == 4 || y == -1) {
System.out.println();
public static boolean aKnownBeaconIsAt(int x, int y) {
return sensors.stream().anyMatch(s -> s.nearestBeaconX == x && s.nearestBeaconY == y);
}
public static boolean isCoveredBySensor(int x, int y) {
return sensors.stream().anyMatch(sensor -> sensor.isNoFartherThanBeacon(x,y));
}
public static int countLocationsThatCannotHaveBeacon(int y) {
int locationsInRangeOfSensor
= IntStream.rangeClosed(minimumX, maximumX).map(x -> isCoveredBySensor(x, y) ? 1 : 0).sum();
int locationsWithKnownBeacon =
IntStream.rangeClosed(minimumX, maximumX).map(x -> aKnownBeaconIsAt(x, y) ? 1 : 0).sum();
return locationsInRangeOfSensor - locationsWithKnownBeacon;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment