2022-12-14 23:11:45 -08:00
|
|
|
use IO, Set, List;
|
|
|
|
|
|
|
|
iter data() {
|
|
|
|
var x1, y1, x2, y2 = 0;
|
|
|
|
while readf("Sensor at x=%i, y=%i: closest beacon is at x=%i, y=%i\n", x1, y1, x2, y2) {
|
|
|
|
yield ((x1, y1), (x2, y2), abs(x1-x2) + abs(y1-y2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
record overlapping {
|
|
|
|
var disjoint: list(range(int));
|
|
|
|
|
|
|
|
proc add(arg: range(int)) {
|
|
|
|
// Don't pollute `disjoint`.
|
|
|
|
if arg.isEmpty() then return;
|
|
|
|
|
|
|
|
var newRng = arg;
|
|
|
|
do {
|
|
|
|
var merged = false;
|
|
|
|
for (rng, i) in zip(disjoint, 0..) {
|
|
|
|
if newRng[rng].isEmpty() then continue;
|
|
|
|
newRng = min(rng.lowBound, newRng.lowBound)..max(rng.highBound, newRng.highBound);
|
|
|
|
disjoint.pop(i);
|
|
|
|
merged = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while merged;
|
|
|
|
disjoint.append(newRng);
|
|
|
|
}
|
|
|
|
|
|
|
|
iter these() { for rng in disjoint do yield rng; }
|
|
|
|
proc size { return + [rng in this] rng.size; }
|
|
|
|
proc boundedSize(bound) { return + reduce [rng in this] rng[bound].size; }
|
|
|
|
proc contains(x) { return || reduce [rng in this] rng.contains(x); }
|
|
|
|
}
|
|
|
|
|
|
|
|
enum axis { xAxis = 0, yAxis = 1 };
|
|
|
|
proc ((int, int)).rangeAlong(axs: axis, reach: int, theXOrY: int) {
|
|
|
|
const dim = axs : int;
|
|
|
|
const dist = abs(this[dim]-theXOrY);
|
|
|
|
|
|
|
|
// Too far
|
|
|
|
if dist > reach then return 0..<0;
|
|
|
|
|
|
|
|
// Get the range
|
|
|
|
const remDist = max(0, reach-dist);
|
|
|
|
return (this[1-dim]-remDist)..(this[1-dim]+remDist);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
config const theY = 10;
|
|
|
|
const searchSpace = 0..theY * 2;
|
|
|
|
const input = data();
|
|
|
|
|
|
|
|
// Solve part 1
|
|
|
|
var overlaps: overlapping;
|
|
|
|
var occupied: set((int, int));
|
|
|
|
for (sensor, beacon, reach) in input {
|
|
|
|
occupied.add(sensor);
|
|
|
|
occupied.add(beacon);
|
2022-12-14 23:13:49 -08:00
|
|
|
overlaps.add(sensor.rangeAlong(axis.yAxis, reach, theY));
|
2022-12-14 23:11:45 -08:00
|
|
|
}
|
|
|
|
writeln(overlaps.size - (+ reduce [(x,y) in occupied] if y == theY then 1));
|
|
|
|
|
|
|
|
// Solve part 2
|
|
|
|
forall checkY in searchSpace {
|
|
|
|
var overlaps: overlapping;
|
|
|
|
for (sensor, _, reach) in input {
|
2022-12-14 23:13:49 -08:00
|
|
|
overlaps.add(sensor.rangeAlong(axis.yAxis, reach, checkY));
|
2022-12-14 23:11:45 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if overlaps.boundedSize(searchSpace) != searchSpace.size {
|
|
|
|
// Found the y-cordinate. Now find the x-coordinate.
|
|
|
|
for checkX in searchSpace {
|
|
|
|
if !overlaps.contains(checkX) {
|
|
|
|
// x-coord isn't in the interval, so we found our answer.
|
|
|
|
writeln("x = ", checkX, ", y = ", checkY, ", frequency = ", checkX * 4000000 + checkY);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|