On Monday, 3 April 2023 at 23:13:58 UTC, Steven Schveighoffer
wrote:
Yeah, please post.
```d
module aoc2215b2;
import std.stdio;
import std.file: readText;
import std.conv: to;
import std.math: abs;
import std.traits;
import std.parallelism;
import std.range;
import core.time: MonoTime;
// Timed main()
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
void main(string[] args) {
auto progStartTime = MonoTime.currTime;
//-----------------------------------------------------------------------------
string filename = args.length > 1 ? args[1] : "aoc2215a.data";
CommPair[] commPair;
ulong x,y;
// read file that has data sets in the form of x,y coordinate
pairs
// for each sensor-beacon pair. Create on array of structs to
hold
// this information.
loadFileDataIntoArrayOfStructs(commPair, filename);
foreach(int lineOfInterest;parallel(iota(0,4_000_001))) {
Span[] span; // A section of line-of-interest coordinates where
no other beacons are present.
const spanReserve = span.reserve(50);
createSpansOfNoBeacons(lineOfInterest,commPair,span);
// if spans overlap, combine them into a single span and mark
// the other spans !inUse.
combineOverlappingSpans(span);
// look for a line that doesn't have 4,000,001 locations
accounted for
if(beaconFreeLocations(span) < 4_000_001) {
// find the location that is not accounted for
foreach(ulong i;0..4_000_000) {
bool found = false;
foreach(sp;span) {
if(i >= sp.xLow && i <= sp.xHigh) {
found = true;
break;
}
}
if(!found) {
x = i; y = lineOfInterest;
break;
}
}
}
}
writeln(x," ",y);
//-----------------------------------------------------------------------------
auto progEndTime = MonoTime.currTime;
writeln(progEndTime - progStartTime);
}
// Timed main()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
struct CommPair {
int sx,sy,bx,by;
int manhattanDistance;
}
void loadFileDataIntoArrayOfStructs(ref CommPair[] commPair,
string filename) {
import std.regex;
auto s = readText(filename);
auto ctr = ctRegex!(`x=(-*\d+), y=(-*\d+):.*x=(-*\d+),
y=(-*\d+)`);
CommPair cptemp;
foreach (c; matchAll(s, ctr)) {
cptemp.sx = to!int(c[1]);
cptemp.sy = to!int(c[2]);
cptemp.bx = to!int(c[3]);
cptemp.by = to!int(c[4]);
cptemp.manhattanDistance = abs(cptemp.sx-cptemp.bx) +
abs(cptemp.sy-cptemp.by);
commPair ~= cptemp;
}
}
struct Span {
int xLow, xHigh;
bool inUse = true;
}
void createSpansOfNoBeacons(int lineOfInterest, CommPair[]
commPair,ref Span[] span) {
foreach(size_t i,cp;commPair) {
int distanceToLineOfInterest = abs(cp.sy - lineOfInterest);
if(cp.manhattanDistance >= distanceToLineOfInterest) {
int xLow = cp.sx - (cp.manhattanDistance -
distanceToLineOfInterest);
int xHigh = cp.sx + (cp.manhattanDistance -
distanceToLineOfInterest);
span ~= Span(xLow,xHigh);
}
}
}
void combineOverlappingSpans(ref Span[] span) {
bool combinedSpansThisCycle = true;
while(combinedSpansThisCycle) {
combinedSpansThisCycle = false;
for(size_t i=0; i < span.length-1; i++) {
if(!span[i].inUse) continue;
for(size_t j=i+1; j < span.length; j++) {
if(!span[j].inUse) continue;
// if one span overlaps with the other, combine them into one
span
if(spanIContainedInSpanJ(span[i],span[j]) ||
spanJContainedInSpanI(span[i],span[j])) {
span[i].xLow = span[i].xLow < span[j].xLow ? span[i].xLow
: span[j].xLow;
span[i].xHigh = span[i].xHigh > span[j].xHigh ?
span[i].xHigh : span[j].xHigh;
span[j].inUse = false;
combinedSpansThisCycle = true;
// after combining two spans, perform
bounds checking
// 15 part b limits the search between
0 and 4,000,000
span[i].xLow = span[i].xLow < 0 ? 0 :
span[i].xLow;
span[i].xHigh = span[i].xHigh > 4_000_000 ? 4_000_000 :
span[i].xHigh;
}
}
}
}
}
bool spanIContainedInSpanJ (Span spanI, Span spanJ) {
return (spanI.xLow >= spanJ.xLow && spanI.xLow <= spanJ.xHigh)
||
(spanI.xHigh>= spanJ.xLow && spanI.xHigh<= spanJ.xHigh);
}
bool spanJContainedInSpanI (Span spanI, Span spanJ) {
return (spanJ.xLow >= spanI.xLow && spanJ.xLow <= spanI.xHigh)
||
(spanJ.xHigh>= spanI.xLow && spanJ.xHigh<= spanI.xHigh);
}
int beaconFreeLocations(ref Span[] span) {
int noBeaconCount = 0;
foreach(sp;span) if(sp.inUse) noBeaconCount += sp.xHigh -
sp.xLow + 1;
return noBeaconCount;
}
```