From 3626395625cbf65154ee1edb14e96913ecd8b3d8 Mon Sep 17 00:00:00 2001
From: Christopher Bohn <bohn@unl.edu>
Date: Fri, 16 Dec 2022 14:21:30 -0600
Subject: [PATCH] Day 15 part 1 complete
---
2022/README.md | 9 ++
.../java/edu/unl/cse/bohn/year2022/Day15.java | 117 +++++-------------
2 files changed, 41 insertions(+), 85 deletions(-)
diff --git a/2022/README.md b/2022/README.md
index 9781814..c8dbb38 100644
--- a/2022/README.md
+++ b/2022/README.md
@@ -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
...
diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day15.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day15.java
index 8cf52ca..dfbed89 100644
--- a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day15.java
+++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day15.java
@@ -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 Sensor getSensorDetectingBeaconAt(int x, int y ) {
+ 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 boolean aKnownBeaconIsAt(int x, int y) {
+ return sensors.stream().anyMatch(s -> s.nearestBeaconX == x && s.nearestBeaconY == y);
}
- 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 boolean isCoveredBySensor(int x, int y) {
+ return sensors.stream().anyMatch(sensor -> sensor.isNoFartherThanBeacon(x,y));
}
- 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 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;
}
}
}
--
GitLab