This commit is contained in:
Ingy döt Net 2013-04-10 16:57:12 -07:00
parent 518da4a923
commit 764da6cbbb
6144 changed files with 83610 additions and 11 deletions

View file

@ -0,0 +1,55 @@
(defun point-distance (p1 p2)
(destructuring-bind (x1 . y1) p1
(destructuring-bind (x2 . y2) p2
(let ((dx (- x2 x1)) (dy (- y2 y1)))
(sqrt (+ (* dx dx) (* dy dy)))))))
(defun closest-pair-bf (points)
(let ((pair (list (first points) (second points)))
(dist (point-distance (first points) (second points))))
(dolist (p1 points (values pair dist))
(dolist (p2 points)
(unless (eq p1 p2)
(let ((pdist (point-distance p1 p2)))
(when (< pdist dist)
(setf (first pair) p1
(second pair) p2
dist pdist))))))))
(defun closest-pair (points)
(labels
((cp (xp &aux (length (length xp)))
(if (<= length 3)
(multiple-value-bind (pair distance) (closest-pair-bf xp)
(values pair distance (sort xp '< :key 'cdr)))
(let* ((xr (nthcdr (1- (floor length 2)) xp))
(xm (/ (+ (caar xr) (caadr xr)) 2)))
(psetf xr (rest xr)
(rest xr) '())
(multiple-value-bind (lpair ldist yl) (cp xp)
(multiple-value-bind (rpair rdist yr) (cp xr)
(multiple-value-bind (dist pair)
(if (< ldist rdist)
(values ldist lpair)
(values rdist rpair))
(let* ((all-ys (merge 'vector yl yr '< :key 'cdr))
(ys (remove-if #'(lambda (p)
(> (abs (- (car p) xm)) dist))
all-ys))
(ns (length ys)))
(dotimes (i ns)
(do ((k (1+ i) (1+ k)))
((or (= k ns)
(> (- (cdr (aref ys k))
(cdr (aref ys i)))
dist)))
(let ((pd (point-distance (aref ys i)
(aref ys k))))
(when (< pd dist)
(setf dist pd
(first pair) (aref ys i)
(second pair) (aref ys k))))))
(values pair dist all-ys)))))))))
(multiple-value-bind (pair distance)
(cp (sort (copy-list points) '< :key 'car))
(values pair distance))))

View file

@ -0,0 +1,68 @@
import std.stdio, std.typecons, std.math, std.algorithm,
std.array, std.random, std.traits;
auto bruteForceClosestPair(T)(in T[] points) pure nothrow {
auto minD = Unqual!(typeof(T.re)).infinity;
Unqual!T minI, minJ;
foreach (i, p1; points[0 .. $-1])
foreach (j, p2; points[i+1 .. $]) {
immutable dist = abs(p1 - p2);
if (dist < minD) {
minD = dist;
minI = p1;
minJ = p2;
}
}
return tuple(minD, minI, minJ);
}
auto closestPair(T)(T[] points) /*pure nothrow*/ {
static Tuple!(typeof(T.re),T,T) inner(in T[] xP, /*in*/ T[] yP) {
if (xP.length <= 3)
return bruteForceClosestPair(xP);
const Pl = xP[0 .. xP.length/2];
const Pr = xP[xP.length/2 .. $];
immutable xDiv = Pl[$ - 1].re;
auto Yr = partition!(p => p.re <= xDiv)(yP);
immutable dl_pairl = inner(Pl, yP[0 .. yP.length - Yr.length]);
immutable dr_pairr = inner(Pr, Yr);
immutable dm_pairm= dl_pairl[0]<dr_pairr[0] ? dl_pairl : dr_pairr;
immutable dm = dm_pairm[0];
const nextY= yP.filter!(p => abs(p.re - xDiv) < dm)().array();
if (nextY.length > 1) {
auto minD = typeof(T.re).infinity;
size_t minI, minJ;
foreach (i; 0 .. nextY.length-1)
foreach (j; i+1 .. min(i+8, nextY.length)) {
immutable double dist = abs(nextY[i] - nextY[j]);
if (dist < minD) {
minD = dist;
minI = i;
minJ = j;
}
}
return dm <= minD ? dm_pairm :
Tuple!(typeof(T.re),T,T)(minD,nextY[minI],nextY[minJ]);
} else
return dm_pairm;
}
sort!q{ a.re < b.re }(points);
auto xP = points.dup;
sort!q{ a.im < b.im }(points);
return inner(xP, points);
}
void main() {
auto pts= [5+9i, 9+3i, 2, 8+4i, 7+4i, 9+10i, 1+9i, 8+2i, 10i, 9+6i];
writeln(pts);
writeln("bruteForceClosestPair: ", bruteForceClosestPair(pts));
writeln(" closestPair: ", closestPair(pts));
auto rnd = Random(1); // set seed
cdouble[10_000] points;
foreach (ref p; points)
p = uniform(0.0, 1000.0, rnd) + uniform(0.0, 1000.0, rnd) * 1i;
writeln("bruteForceClosestPair: ", bruteForceClosestPair(points));
writeln(" closestPair: ", closestPair(points));
}

View file

@ -0,0 +1,49 @@
import core.stdc.stdio, core.stdc.stdlib, std.math; // for Phobos
//import tango.stdc.stdio, tango.stdc.stdlib, tango.math.Math;
int bfClosestPair2(cdouble[] points, out size_t i1, out size_t i2) {
auto minD = typeof(points[0].re).infinity;
if (points.length < 2) {
i1 = i2 = size_t.max;
return -1;
}
size_t minI, minJ;
for (int i = 0; i < points.length-1; i++) {
auto points_i_re = points[i].re;
auto points_i_im = points[i].im;
for (int j = i+1; j < points.length; j++) {
auto dre = points_i_re - points[j].re;
auto dist = dre * dre;
if (dist < minD) {
auto dim = points_i_im - points[j].im;
dist += dim * dim;
if (dist < minD) {
minD = dist;
minI = i;
minJ = j;
}
}
}
}
i1 = minI;
i2 = minJ;
return 0;
}
void main() {
srand(31415);
auto pts = new cdouble[10_000];
foreach (ref p; pts)
p = 1000.0 * (cast(double)rand() / (RAND_MAX + 1.0)) +
1000.0i * (cast(double)rand() / (RAND_MAX + 1.0));
size_t i, j;
int err = bfClosestPair2(pts, i, j);
if (err < 0)
return;
double d = sqrt((pts[i].re - pts[j].re) * (pts[i].re - pts[j].re) +
(pts[i].im - pts[j].im) * (pts[i].im - pts[j].im));
printf("Closest pair: dist: %lf p1, p2: (%lf, %lf), (%lf, %lf)\n",
d, pts[i].re, pts[i].im, pts[j].re, pts[j].im);
}