June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -50,7 +50,7 @@ std::pair<double, points_t> find_closest_optimized(const std::vector<point_t>& x
|
|||
auto xR = std::vector<point_t>();
|
||||
std::copy(std::begin(xP), std::begin(xP) + (N / 2), std::back_inserter(xL));
|
||||
std::copy(std::begin(xP) + (N / 2), std::end(xP), std::back_inserter(xR));
|
||||
auto xM = xP.at(N / 2).first;
|
||||
auto xM = xP.at((N-1) / 2).first;
|
||||
auto yL = std::vector<point_t>();
|
||||
auto yR = std::vector<point_t>();
|
||||
std::copy_if(std::begin(yP), std::end(yP), std::back_inserter(yL), [&xM](const point_t& p) {
|
||||
|
|
|
|||
70
Task/Closest-pair-problem/Maple/closest-pair-problem-1.maple
Normal file
70
Task/Closest-pair-problem/Maple/closest-pair-problem-1.maple
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
ClosestPair := module()
|
||||
|
||||
local
|
||||
ModuleApply := proc(L::list,$)
|
||||
local Lx, Ly, out;
|
||||
Ly := sort(L, 'key'=(i->i[2]), 'output'='permutation');
|
||||
Lx := sort(L, 'key'=(i->i[1]), 'output'='permutation');
|
||||
out := Recurse(L, Lx, Ly, 1, numelems(L));
|
||||
return sqrt(out[1]), out[2];
|
||||
end proc; # ModuleApply
|
||||
|
||||
local
|
||||
BruteForce := proc(L, Lx, r1:=1, r2:=numelems(L), $)
|
||||
local d, p, n, i, j;
|
||||
d := infinity;
|
||||
for i from r1 to r2-1 do
|
||||
for j from i+1 to r2 do
|
||||
n := dist( L[Lx[i]], L[Lx[j]] );
|
||||
if n < d then
|
||||
d := n;
|
||||
p := [ L[Lx[i]], L[Lx[j]] ];
|
||||
end if;
|
||||
end do; # j
|
||||
end do; # i
|
||||
return (d, p);
|
||||
end proc; # BruteForce
|
||||
|
||||
local dist := (p, q)->(( (p[1]-q[1])^2+(p[2]-q[2])^2 ));
|
||||
|
||||
local Recurse := proc(L, Lx, Ly, r1, r2)
|
||||
local m, xm, rDist, rPair, lDist, lPair, minDist, minPair, S, i, j, Lyr, Lyl;
|
||||
|
||||
if r2-r1 <= 3 then
|
||||
return BruteForce(L, Lx, r1, r2);
|
||||
end if;
|
||||
|
||||
m := ceil((r2-r1)/2)+r1;
|
||||
xm := (L[Lx[m]][1] + L[Lx[m-1]][1])/2;
|
||||
|
||||
(Lyr, Lyl) := selectremove( i->L[i][1] < xm, Ly);
|
||||
|
||||
(rDist, rPair) := thisproc(L, Lx, Lyr, r1, m-1);
|
||||
(lDist, lPair) := thisproc(L, Lx, Lyl, m, r2);
|
||||
|
||||
if rDist < lDist then
|
||||
minDist := rDist;
|
||||
minPair := rPair;
|
||||
else
|
||||
minDist := lDist;
|
||||
minPair := lPair;
|
||||
end if;
|
||||
|
||||
S := [ seq( `if`(abs(xm - L[i][1])^2< minDist, L[i], NULL ), i in Ly ) ];
|
||||
|
||||
for i from 1 to nops(S)-1 do
|
||||
for j from i+1 to nops(S) do
|
||||
if abs( S[i][2] - S[j][2] )^2 >= minDist then
|
||||
break;
|
||||
elif dist(S[i], S[j]) < minDist then
|
||||
minDist := dist(S[i], S[j]);
|
||||
minPair := [S[i], S[j]];
|
||||
end if;
|
||||
end do;
|
||||
end do;
|
||||
|
||||
return (minDist, minPair);
|
||||
|
||||
end proc; #Recurse
|
||||
|
||||
end module; #ClosestPair
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
> L := RandomTools:-Generate(list(list(float(range=0..1),2),512)):
|
||||
> ClosestPair(L);
|
||||
0.002576770304, [[0.4265584800, 0.7443097852], [0.4240649736, 0.7449595321]]
|
||||
30
Task/Closest-pair-problem/Prolog/closest-pair-problem-1.pro
Normal file
30
Task/Closest-pair-problem/Prolog/closest-pair-problem-1.pro
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
% main predicate, find and print closest point
|
||||
do_find_closest_points(Points) :-
|
||||
points_closest(Points, points(point(X1,Y1),point(X2,Y2),Dist)),
|
||||
format('Point 1 : (~p, ~p)~n', [X1,Y1]),
|
||||
format('Point 1 : (~p, ~p)~n', [X2,Y2]),
|
||||
format('Distance: ~p~n', [Dist]).
|
||||
|
||||
% Find the distance between two points
|
||||
distance(point(X1,Y1), point(X2,Y2), points(point(X1,Y1),point(X2,Y2),Dist)) :-
|
||||
Dx is X2 - X1,
|
||||
Dy is Y2 - Y1,
|
||||
Dist is sqrt(Dx * Dx + Dy * Dy).
|
||||
|
||||
% find the closest point that relatest to another point
|
||||
point_closest(Points, Point, Closest) :-
|
||||
select(Point, Points, Remaining),
|
||||
maplist(distance(Point), Remaining, PointList),
|
||||
foldl(closest, PointList, 0, Closest).
|
||||
|
||||
% find the closest point/dist pair for all points
|
||||
points_closest(Points, Closest) :-
|
||||
maplist(point_closest(Points), Points, ClosestPerPoint),
|
||||
foldl(closest, ClosestPerPoint, 0, Closest).
|
||||
|
||||
% used by foldl to get the lowest point/distance combination
|
||||
closest(points(P1,P2,Dist), 0, points(P1,P2,Dist)).
|
||||
closest(points(_,_,Dist), points(P1,P2,Dist2), points(P1,P2,Dist2)) :-
|
||||
Dist2 < Dist.
|
||||
closest(points(P1,P2,Dist), points(_,_,Dist2), points(P1,P2,Dist)) :-
|
||||
Dist =< Dist2.
|
||||
12
Task/Closest-pair-problem/Prolog/closest-pair-problem-2.pro
Normal file
12
Task/Closest-pair-problem/Prolog/closest-pair-problem-2.pro
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
do_find_closest_points([
|
||||
point(0.654682, 0.925557),
|
||||
point(0.409382, 0.619391),
|
||||
point(0.891663, 0.888594),
|
||||
point(0.716629, 0.996200),
|
||||
point(0.477721, 0.946355),
|
||||
point(0.925092, 0.818220),
|
||||
point(0.624291, 0.142924),
|
||||
point(0.211332, 0.221507),
|
||||
point(0.293786, 0.691701),
|
||||
point(0.839186, 0.728260)
|
||||
]).
|
||||
|
|
@ -1,32 +1,30 @@
|
|||
/*REXX program solves the closest pair of points problem (in two dimensions). */
|
||||
parse arg N low high seed . /*obtain optional arguments from the CL*/
|
||||
if N=='' | N=="," then N= 100 /*Not specified? Then use the default.*/
|
||||
if low=='' | low=="," then low= 0 /* " " " " " " */
|
||||
if high=='' | high=="," then high=20000 /* " " " " " " */
|
||||
if datatype(seed,'W') then call random ,,seed /*seed for RANDOM (BIF) repeatability.*/
|
||||
w=length(high); w=w + (w//2==0)
|
||||
/*╔══════════════════════╗*/ do j=1 for N /*generate N random points.*/
|
||||
/*║ generate N points. ║*/ @x.j=random(low,high) /* " a random X. */
|
||||
/*╚══════════════════════╝*/ @y.j=random(low,high) /* " " " Y. */
|
||||
end /*j*/ /*X and Y make the point*/
|
||||
A=1; B=2 /* [↓] MINDD is actually the unsquared*/
|
||||
minDD=(@x.A-@x.B)**2 + (@y.A-@y.B)**2 /*distance between the first two points*/
|
||||
if N=='' | N=="," then N= 100 /*Not specified? Then use the default.*/
|
||||
if low=='' | low=="," then low= 0 /* " " " " " " */
|
||||
if high=='' | high=="," then high= 20000 /* " " " " " " */
|
||||
if datatype(seed, 'W') then call random ,,seed /*seed for RANDOM (BIF) repeatability.*/
|
||||
w=length(high); w=w + (w//2==0) /*W: for aligning the output columns.*/
|
||||
/*╔══════════════════════╗*/ do j=1 for N /*generate N random points*/
|
||||
/*║ generate N points. ║*/ @x.j=random(low, high) /* " a random X */
|
||||
/*╚══════════════════════╝*/ @y.j=random(low, high) /* " " " Y */
|
||||
end /*j*/ /*X & Y make the point.*/
|
||||
A=1; B=2 /* [↓] MINDD is actually the squared*/
|
||||
minDD= (@x.A - @x.B)**2 + (@y.A - @y.B)**2 /*distance between the first two points*/
|
||||
/* [↓] use of XJ & YJ speed things up.*/
|
||||
do j=1 for N-1; xj=@x.j; yj=@y.j /*find minimum distance between a ··· */
|
||||
do k=j+1 to N /* ··· point and all the other points.*/
|
||||
dd=(xj - @x.k)**2 + (yj - @y.k)**2 /*compute squared distance from points.*/
|
||||
if dd<minDD then if dd\=0 then parse value dd j k with minDD A B
|
||||
end /*k*/ /* [↑] needn't take SQRT of DD (yet).*/
|
||||
end /*j*/ /* [↑] when done, A & B are the ones*/
|
||||
|
||||
_= 'For ' N " points, the minimum distance between the two points: "
|
||||
say _ center("x", w, '═')" " center('y', w, "═") ' is: ' sqrt(abs(minDD))/1
|
||||
say left('', length(_)-1) "["right(@x.A, w)',' right(@y.A, w)"]"
|
||||
say left('', length(_)-1) "["right(@x.B, w)',' right(@y.B, w)"]"
|
||||
do j=1 for N-1; xj=@x.j; yj=@y.j /*find minimum distance between a ··· */
|
||||
do k=j+1 to N /* ··· point and all the other points.*/
|
||||
dd=(xj - @x.k)**2 + (yj - @y.k)**2 /*compute squared distance from points.*/
|
||||
if dd<minDD then parse value dd j k with minDD A B
|
||||
end /*k*/ /* [↑] needn't take SQRT of DD (yet).*/
|
||||
end /*j*/ /* [↑] when done, A & B are the points*/
|
||||
$= 'For ' N " points, the minimum distance between the two points: "
|
||||
say $ center("x", w, '═')" " center('y', w, "═") ' is: ' sqrt(abs(minDD))/1
|
||||
say left('', length($) - 1) "["right(@x.A, w)',' right(@y.A, w)"]"
|
||||
say left('', length($) - 1) "["right(@x.B, w)',' right(@y.B, w)"]"
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); m.=9; numeric form; h=d+6
|
||||
numeric digits; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g *.5'e'_ % 2
|
||||
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
|
||||
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
|
||||
return g
|
||||
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
|
||||
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g
|
||||
|
|
|
|||
|
|
@ -1,2 +1,97 @@
|
|||
Closest points: (0+1i 1+2i)
|
||||
Distance: 1.4142135623730951
|
||||
#lang racket
|
||||
(struct point (x y) #:transparent)
|
||||
|
||||
(define (closest-pair ps)
|
||||
(check-type ps)
|
||||
(cond [(vector? ps) (if (> (vector-length ps) 1)
|
||||
(closest-pair/sorted (vector-sort ps left?)
|
||||
(vector-sort ps below?))
|
||||
(error 'closest-pair "2 or more points are needed" ps))]
|
||||
[(sequence? ps) (closest-pair (for/vector ([x (in-sequences ps)]) x))]
|
||||
[else (error 'closest-pair "closest pair only supports sequence types (excluding hash)")]))
|
||||
|
||||
;; accept any sequence type except hash
|
||||
;; any other exclusions needed?
|
||||
(define (check-type ps)
|
||||
(cond [(hash? ps) (error 'closest-pair "Hash tables are not supported")]
|
||||
[(sequence? ps) #t]
|
||||
[else (error 'closest-pair "Only sequence types are supported")]))
|
||||
|
||||
;; vector -> vector -> list
|
||||
(define (closest-pair/sorted Px Py)
|
||||
(define L (vector-length Px))
|
||||
(cond [(= L 2) (vector->list Px)]
|
||||
[(= L 3) (apply min-pair (combinations (vector->list Px) 2))]
|
||||
[else (let*-values ([(Qx Rx) (vector-split-at Px (floor (/ L 2)))]
|
||||
; Rx-min is the left most point in Rx
|
||||
[(Rx-min) (vector-ref Rx 0)]
|
||||
; instead of sorting Qx, Rx by y
|
||||
; - Qy are members of Py to left of Rx-min
|
||||
; - Ry are the remaining members of Py
|
||||
[(Qy Ry) (vector-partition Py (curryr left? Rx-min))]
|
||||
[(pair1) (closest-pair/sorted Qx Qy)]
|
||||
[(pair2) (closest-pair/sorted Rx Ry)]
|
||||
[(delta) (min (distance^2 pair1) (distance^2 pair2))]
|
||||
[(pair3) (closest-split-pair Px Py delta)])
|
||||
; pair3 is null when there are no split pairs closer than delta
|
||||
(min-pair pair1 pair2 pair3))]))
|
||||
|
||||
(define (closest-split-pair Px Py delta)
|
||||
(define Lp (vector-length Px))
|
||||
(define x-mid (point-x (vector-ref Px (floor (/ Lp 2)))))
|
||||
(define Sy (for/vector ([p (in-vector Py)]
|
||||
#:when (< (abs (- (point-x p) x-mid)) delta))
|
||||
p))
|
||||
(define Ls (vector-length Sy))
|
||||
(define-values (_ best-pair)
|
||||
(for*/fold ([new-best delta]
|
||||
[new-best-pair null])
|
||||
([i (in-range (sub1 Ls))]
|
||||
[j (in-range (+ i 1) (min (+ i 7) Ls))]
|
||||
[Sij (in-value (list (vector-ref Sy i)
|
||||
(vector-ref Sy j)))]
|
||||
[dij (in-value (distance^2 Sij))]
|
||||
#:when (< dij new-best))
|
||||
(values dij Sij)))
|
||||
best-pair)
|
||||
|
||||
;; helper procedures
|
||||
|
||||
;; same as partition except for vectors
|
||||
;; it's critical to maintain the relative order of elements
|
||||
(define (vector-partition Py pred)
|
||||
(define-values (left right)
|
||||
(for/fold ([Qy null]
|
||||
[Ry null])
|
||||
([p (in-vector Py)])
|
||||
(if (pred p)
|
||||
(values (cons p Qy) Ry)
|
||||
(values Qy (cons p Ry)))))
|
||||
(values (list->vector (reverse left))
|
||||
(list->vector (reverse right))))
|
||||
|
||||
; is p1 (strictly) left of p2
|
||||
(define (left? p1 p2) (< (point-x p1) (point-x p2)))
|
||||
|
||||
; is p1 (strictly) below of p2
|
||||
(define (below? p1 p2) (< (point-y p1) (point-y p2)))
|
||||
|
||||
;; return the pair with minimum distance
|
||||
(define (min-pair . pairs)
|
||||
(argmin distance^2 pairs))
|
||||
|
||||
;; pairs are passed around as a list of 2 points
|
||||
;; distance is only for comparison so no need to use sqrt
|
||||
(define (distance^2 pair)
|
||||
(cond [(null? pair) +inf.0]
|
||||
[else (define a (first pair))
|
||||
(define b (second pair))
|
||||
(+ (sqr (- (point-x b) (point-x a)))
|
||||
(sqr (- (point-y b) (point-y a))))]))
|
||||
|
||||
; points on a quadratic curve, shuffled
|
||||
(define points
|
||||
(shuffle
|
||||
(for/list ([ i (in-range 1000)]) (point i (* i i)))))
|
||||
(match-define (list (point p1x p1y) (point p2x p2y)) (closest-pair points))
|
||||
(printf "Closest points on a quadratic curve (~a,~a) (~a,~a)\n" p1x p1y p2x p2y)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
Closest points: (0+1i 1+2i)
|
||||
Distance: 1.4142135623730951
|
||||
|
||||
Closest points on a quadratic curve (0,0) (1,1)
|
||||
53
Task/Closest-pair-problem/VBA/closest-pair-problem.vba
Normal file
53
Task/Closest-pair-problem/VBA/closest-pair-problem.vba
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
Option Explicit
|
||||
|
||||
Private Type MyPoint
|
||||
X As Single
|
||||
Y As Single
|
||||
End Type
|
||||
|
||||
Private Type MyPair
|
||||
p1 As MyPoint
|
||||
p2 As MyPoint
|
||||
End Type
|
||||
|
||||
Sub Main()
|
||||
Dim points() As MyPoint, i As Long, BF As MyPair, d As Single, Nb As Long
|
||||
Dim T#
|
||||
Randomize Timer
|
||||
Nb = 10
|
||||
Do
|
||||
ReDim points(1 To Nb)
|
||||
For i = 1 To Nb
|
||||
points(i).X = Rnd * Nb
|
||||
points(i).Y = Rnd * Nb
|
||||
Next
|
||||
d = 1000000000000#
|
||||
T = Timer
|
||||
BF = BruteForce(points, d)
|
||||
Debug.Print "For " & Nb & " points, runtime : " & Timer - T & " sec."
|
||||
Debug.Print "point 1 : X:" & BF.p1.X & " Y:" & BF.p1.Y
|
||||
Debug.Print "point 2 : X:" & BF.p2.X & " Y:" & BF.p2.Y
|
||||
Debug.Print "dist : " & d
|
||||
Debug.Print "--------------------------------------------------"
|
||||
Nb = Nb * 10
|
||||
Loop While Nb <= 10000
|
||||
End Sub
|
||||
|
||||
Private Function BruteForce(p() As MyPoint, mindist As Single) As MyPair
|
||||
Dim i As Long, j As Long, d As Single, ClosestPair As MyPair
|
||||
For i = 1 To UBound(p) - 1
|
||||
For j = i + 1 To UBound(p)
|
||||
d = Dist(p(i), p(j))
|
||||
If d < mindist Then
|
||||
mindist = d
|
||||
ClosestPair.p1 = p(i)
|
||||
ClosestPair.p2 = p(j)
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
BruteForce = ClosestPair
|
||||
End Function
|
||||
|
||||
Private Function Dist(p1 As MyPoint, p2 As MyPoint) As Single
|
||||
Dist = Sqr((p1.X - p2.X) ^ 2 + (p1.Y - p2.Y) ^ 2)
|
||||
End Function
|
||||
Loading…
Add table
Add a link
Reference in a new issue