function closestpair(P::Vector{Vector{T}}) where T <: Number
    N = length(P)
    if N < 2 return (Inf, ()) end
    mindst = norm(P[1] - P[2])
    minpts = (P[1], P[2])
    for i in 1:N-1, j in i+1:N
        tmpdst = norm(P[i] - P[j])
        if tmpdst < mindst
            mindst = tmpdst
            minpts = (P[i], P[j])
        end
    end
    return mindst, minpts
end

closestpair([[0, -0.3], [1., 1.], [1.5, 2], [2, 2], [3, 3]])


// version 1.1.2

typealias Point = Pair<Double, Double>

fun distance(p1: Point, p2: Point) = Math.hypot(p1.first- p2.first, p1.second - p2.second)

fun bruteForceClosestPair(p: List<Point>): Pair<Double, Pair<Point, Point>> {
    val n = p.size
    if (n < 2) throw IllegalArgumentException("Must be at least two points")
    var minPoints = p[0] to p[1]
    var minDistance = distance(p[0], p[1])
    for (i in 0 until n - 1)
        for (j in i + 1 until n) {
            val dist = distance(p[i], p[j])
            if (dist < minDistance) {
                minDistance = dist
                minPoints = p[i] to p[j]
            }
        }
    return minDistance to Pair(minPoints.first, minPoints.second)
}

fun optimizedClosestPair(xP: List<Point>, yP: List<Point>): Pair<Double, Pair<Point, Point>> {
    val n = xP.size
    if (n <= 3) return bruteForceClosestPair(xP)
    val xL = xP.take(n / 2)
    val xR = xP.drop(n / 2)
    val xm = xP[n / 2 - 1].first
    val yL = yP.filter { it.first <= xm }
    val yR = yP.filter { it.first >  xm }
    val (dL, pairL) = optimizedClosestPair(xL, yL)
    val (dR, pairR) = optimizedClosestPair(xR, yR)
    var dmin = dR
    var pairMin = pairR
    if (dL < dR) {
        dmin = dL
        pairMin = pairL
    }
    val yS = yP.filter { Math.abs(xm - it.first) < dmin }
    val nS = yS.size
    var closest = dmin
    var closestPair = pairMin
    for (i in 0 until nS - 1) {
        var k = i + 1
        while (k < nS && (yS[k].second - yS[i].second < dmin)) {
            val dist = distance(yS[k], yS[i])
            if (dist < closest) {
                closest = dist
                closestPair = Pair(yS[k], yS[i])
            }
            k++
        }
    }
    return closest to closestPair
}

fun main(args: Array<String>) {
    val points = listOf(
        listOf(
            5.0 to  9.0, 9.0 to 3.0,  2.0 to 0.0, 8.0 to  4.0, 7.0 to 4.0,
            9.0 to 10.0, 1.0 to 9.0,  8.0 to 2.0, 0.0 to 10.0, 9.0 to 6.0
        ),
        listOf(
            0.654682 to 0.925557, 0.409382 to 0.619391, 0.891663 to 0.888594,
            0.716629 to 0.996200, 0.477721 to 0.946355, 0.925092 to 0.818220,
            0.624291 to 0.142924, 0.211332 to 0.221507, 0.293786 to 0.691701,
            0.839186 to 0.728260
        )
    )
    for (p in points) {
        val (dist, pair) = bruteForceClosestPair(p)
        println("Closest pair (brute force) is ${pair.first} and ${pair.second}, distance $dist")
        val xP = p.sortedBy { it.first }
        val yP = p.sortedBy { it.second }
        val (dist2, pair2) = optimizedClosestPair(xP, yP)
        println("Closest pair (optimized)   is ${pair2.first} and ${pair2.second}, distance $dist2\n")
    }
}


N =10

dim x( N), y( N)

firstPt  =0
secondPt =0

for i =1 to N
    read f: x( i) =f
    read f: y( i) =f
next i

minDistance  =1E6

for i =1 to N -1
    for j =i +1 to N
      dxSq =( x( i) -x( j))^2
      dySq =( y( i) -y( j))^2
      D    =abs( ( dxSq +dySq)^0.5)
      if D <minDistance then
        minDistance =D
        firstPt     =i
        secondPt    =j
      end if
    next j
next i

print "Distance ="; minDistance; " between ( "; x( firstPt); ", "; y( firstPt); ") and ( "; x( secondPt); ", "; y( secondPt); ")"

end

data  0.654682, 0.925557
data  0.409382, 0.619391
data  0.891663, 0.888594
data  0.716629, 0.996200
data  0.477721, 0.946355
data  0.925092, 0.818220
data  0.624291, 0.142924
data  0.211332, 0.221507
data  0.293786, 0.691701
data  0.839186,  0.72826


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


nearestPair[data_] :=
 Block[{pos, dist = N[Outer[EuclideanDistance, data, data, 1]]},
  pos = Position[dist, Min[DeleteCases[Flatten[dist], 0.]]];
  data[[pos[[1]]]]]


function [closest,closestpair] = closestPair(xP,yP)

    N = numel(xP);

    if(N <= 3)

        %Brute force closestpair
        if(N < 2)
            closest = +Inf;
            closestpair = {};
        else
            closest = norm(xP{1}-xP{2});
            closestpair = {xP{1},xP{2}};

            for i = ( 1:N-1 )
                for j = ( (i+1):N )
                    if ( norm(xP{i} - xP{j}) < closest )
                        closest = norm(xP{i}-xP{j});
                        closestpair = {xP{i},xP{j}};
                    end %if
                end %for
            end %for
        end %if (N < 2)
    else

        halfN = ceil(N/2);

        xL = { xP{1:halfN} };
        xR = { xP{halfN+1:N} };
        xm = xP{halfN}(1);

        %cellfun( @(p)le(p(1),xm),yP ) is the same as { p ∈ yP : px ≤ xm }
        yLIndicies = cellfun( @(p)le(p(1),xm),yP );

        yL = { yP{yLIndicies} };
        yR = { yP{~yLIndicies} };

        [dL,pairL] = closestPair(xL,yL);
        [dR,pairR] = closestPair(xR,yR);

        if dL < dR
            dmin = dL;
            pairMin = pairL;
        else
            dmin = dR;
            pairMin = pairR;
        end

        %cellfun( @(p)lt(norm(xm-p(1)),dmin),yP ) is the same as
        %{ p ∈ yP : |xm - px| < dmin }
        yS = {yP{ cellfun( @(p)lt(norm(xm-p(1)),dmin),yP ) }};
        nS = numel(yS);

        closest = dmin;
        closestpair = pairMin;

        for i = (1:nS-1)
            k = i+1;

            while( (k<=nS) && (yS{k}(2)-yS{i}(2) < dmin) )

                if norm(yS{k}-yS{i}) < closest
                    closest = norm(yS{k}-yS{i});
                    closestpair = {yS{k},yS{i}};
                end

                k = k+1;
            end %while
        end %for
    end %if (N <= 3)
end %closestPair


' Closest Pair Problem
s="0.654682,0.925557,0.409382,0.619391,0.891663,0.888594,0.716629,0.996200,0.477721,0.946355,0.925092,0.818220,0.624291,0.142924,0.211332,0.221507,0.293786,0.691701,0.839186,0.728260,"
  i=0
  While s<>""
    i=i+1
    For j=1 To 2
      k=Text.GetIndexOf(s,",")
      ss=Text.GetSubText(s,1,k-1)
      s=Text.GetSubTextToEnd(s,k+1)
      pxy[i][j]=ss
    EndFor
  EndWhile
  n=i
  i=1
  j=2
  dd=Math.Power(pxy[i][1]-pxy[j][1],2)+Math.Power(pxy[i][2]-pxy[j][2],2)
  ddmin=dd
  ii=i
  jj=j
  For i=1 To n
    For j=1 To n
      dd=Math.Power(pxy[i][1]-pxy[j][1],2)+Math.Power(pxy[i][2]-pxy[j][2],2)
      If dd>0 Then
        If dd<ddmin Then
          ddmin=dd
          ii=i
          jj=j
        EndIf
      EndIf
    EndFor
  EndFor
  sqrt1=ddmin
  sqrt2=ddmin/2
  For i=1 To 20
    If sqrt1=sqrt2 Then
      Goto exitfor
    EndIf
    sqrt1=sqrt2
    sqrt2=(sqrt1+(ddmin/sqrt1))/2
  EndFor
exitfor:
  TextWindow.WriteLine("the minimum distance "+sqrt2)
  TextWindow.WriteLine("is between the points:")
  TextWindow.WriteLine("  ["+pxy[ii][1]+","+pxy[ii][2]+"] and")
  TextWindow.WriteLine("  ["+pxy[jj][1]+","+pxy[jj][2]+"]")


import math, algorithm

type

  Point = tuple[x, y: float]
  Pair = tuple[p1, p2: Point]
  Result = tuple[minDist: float; minPoints: Pair]

#---------------------------------------------------------------------------------------------------

template sqr(x: float): float = x * x

#---------------------------------------------------------------------------------------------------

func dist(point1, point2: Point): float =
  sqrt(sqr(point2.x - point1.x) + sqr(point2.y - point1.y))

#---------------------------------------------------------------------------------------------------

func bruteForceClosestPair*(points: openArray[Point]): Result =

  doAssert(points.len >= 2, "At least two points required.")

  result.minDist = Inf
  for i in 0..<points.high:
    for j in (i + 1)..points.high:
      let d = dist(points[i], points[j])
      if  d < result.minDist:
        result = (d, (points[i], points[j]))

#---------------------------------------------------------------------------------------------------

func closestPair(xP, yP: openArray[Point]): Result =
  ## Recursive function which takes two open arrays as arguments: the first
  ## sorted by increasing values of x, the second sorted by increasing values of y.

  if xP.len <= 3:
    return xP.bruteForceClosestPair()

  let m = xP.high div 2
  let xL = xP[0..m]
  let xR = xP[(m + 1)..^1]

  let xm = xP[m].x
  var yL, yR: seq[Point]
  for p in yP:
    if p.x <= xm: yL.add(p)
    else: yR.add(p)

  let (dL, pairL) = closestPair(xL, yL)
  let (dR, pairR) = closestPair(xR, yR)
  let (dMin, pairMin) = if dL < dR: (dL, pairL) else: (dR, pairR)

  var yS: seq[Point]
  for p in yP:
    if abs(xm - p.x) < dmin: yS.add(p)

  result = (dMin, pairMin)
  for i in 0..<yS.high:
    var k = i + 1
    while k < yS.len and ys[k].y - yS[i].y < dMin:
      let d = dist(yS[i], yS[k])
      if d < result.minDist:
        result = (d, (yS[i], yS[k]))
      inc k

#---------------------------------------------------------------------------------------------------

func closestPair*(points: openArray[Point]): Result =

  let xP = points.sortedByIt(it.x)
  let yP = points.sortedByIt(it.y)
  doAssert(points.len >= 2, "At least two points required.")

  result = closestPair(xP, yP)

#———————————————————————————————————————————————————————————————————————————————————————————————————

import random, times, strformat

randomize()

const N = 50_000
const Max = 10_000.0
var points: array[N, Point]
for pt in points.mitems: pt = (rand(Max), rand(Max))

echo "Sample contains ", N, " random points."
echo ""

let t0 = getTime()
echo "Brute force algorithm:"
echo points.bruteForceClosestPair()
let t1 = getTime()
echo "Optimized algorithm:"
echo points.closestPair()
let t2 = getTime()

echo ""
echo fmt"Execution time for brute force algorithm: {(t1 - t0).inMilliseconds:>4} ms"
echo fmt"Execution time for optimized algorithm:   {(t2 - t1).inMilliseconds:>4} ms"


type point = { x : float; y : float }

let cmpPointX (a : point) (b : point) = compare a.x b.x
let cmpPointY (a : point) (b : point) = compare a.y b.y

let distSqrd (seg : (point * point) option) =
  match seg with
  | None -> max_float
  | Some(line) ->
    let a = fst line in
    let b = snd line in

    let dx = a.x -. b.x in
    let dy = a.y -. b.y in

    dx*.dx +. dy*.dy

let dist seg =
  sqrt (distSqrd seg)

let shortest l1 l2 =
  if distSqrd l1 < distSqrd l2 then
    l1
  else
    l2

let halve l =
  let n = List.length l in
  BatList.split_at (n/2) l

let rec closestBoundY from maxY (ptsByY : point list) =
  match ptsByY with
  | [] -> None
  | hd :: tl ->
    if hd.y > maxY then
      None
    else
      let toHd = Some(from, hd) in
      let bestToRest = closestBoundY from maxY tl in
      shortest toHd bestToRest

let rec closestInRange ptsByY maxDy =
  match ptsByY with
  | [] -> None
  | hd :: tl ->
    let fromHd = closestBoundY hd (hd.y +. maxDy) tl in
    let fromRest = closestInRange tl maxDy in
    shortest fromHd fromRest

let rec closestPairByX (ptsByX : point list) =
   if List.length ptsByX < 2 then
       None
   else
       let (left, right) = halve ptsByX in
       let leftResult = closestPairByX left in
       let rightResult = closestPairByX right in

       let bestInHalf = shortest  leftResult rightResult in
       let bestLength = dist bestInHalf in

       let divideX = (List.hd right).x in
       let inBand = List.filter(fun(p) -> abs_float(p.x -. divideX) < bestLength) ptsByX in

       let byY = List.sort cmpPointY inBand in
       let bestCross = closestInRange byY bestLength in
       shortest bestInHalf bestCross

let closestPair pts =
  let ptsByX = List.sort cmpPointX pts in
  closestPairByX ptsByX

let parsePoint str =
  let sep = Str.regexp_string "," in
  let tokens = Str.split sep str in
  let xStr = List.nth tokens 0 in
  let yStr = List.nth tokens 1 in

  let xVal = (float_of_string xStr) in
  let yVal = (float_of_string yStr) in

  { x = xVal; y = yVal }

let loadPoints filename =
  let ic = open_in filename in
  let result = ref [] in
  try
    while true do
      let s = input_line ic in
      if s <> "" then
        let p = parsePoint s in
        result := p :: !result;
    done;
    !result
  with End_of_file ->
    close_in ic;
    !result
;;

let loaded = (loadPoints "Points.txt") in
let start = Sys.time() in
let c = closestPair loaded in
let taken = Sys.time() -. start in
Printf.printf "Took %f [s]\n" taken;

match c with
| None -> Printf.printf "No closest pair\n"
| Some(seg) ->
  let a = fst seg in
  let b = snd seg in

  Printf.printf "(%f, %f) (%f, %f) Dist %f\n" a.x a.y b.x b.y (dist c)


declare
  fun {Distance X1#Y1 X2#Y2}
     {Sqrt {Pow X2-X1 2.0} + {Pow Y2-Y1 2.0}}
  end

  %% brute force
  fun {BFClosestPair Points=P1|P2|_}
     Ps = {List.toTuple unit Points} %% for efficient random access
     N = {Width Ps}
     MinDist = {NewCell {Distance P1 P2}}
     MinPoints = {NewCell P1#P2}
  in
     for I in 1..N-1 do
        for J in I+1..N do
           IJDist = {Distance Ps.I Ps.J}
        in
           if IJDist < @MinDist then
              MinDist := IJDist
              MinPoints := Ps.I#Ps.J
           end
        end
     end
     @MinPoints
  end

  %% divide and conquer
  fun {ClosestPair Points}
     case {ClosestPair2
           {Sort Points {LessThanBy X}}
           {Sort Points {LessThanBy Y}}}
     of Distance#Pair then
        Pair
     end
  end

  %% XP: points sorted by X, YP: sorted by Y
  %% returns a pair Distance#Pair
  fun {ClosestPair2 XP YP}
     N = {Length XP} = {Length YP}
  in
     if N =< 3 then
        P = {BFClosestPair XP}
     in
        {Distance P.1 P.2}#P
     else
        XL XR
        {List.takeDrop XP (N div 2) ?XL ?XR}
        XM = {Nth XP (N div 2)}.X
        YL YR
        {List.partition YP fun {$ P} P.X =< XM end ?YL ?YR}
        DL#PairL = {ClosestPair2 XL YL}
        DR#PairR = {ClosestPair2 XR YR}
        DMin#PairMin = if DL < DR then DL#PairL else DR#PairR end
        YSList = {Filter YP fun {$ P} {Abs XM-P.X} < DMin end}
        YS = {List.toTuple unit YSList} %% for efficient random access
        NS = {Width YS}
        Closest = {NewCell DMin}
        ClosestPair = {NewCell PairMin}
     in
        for I in 1..NS-1 do
           for K in I+1..NS while:YS.K.Y - YS.I.Y < DMin do
              DistKI = {Distance YS.K YS.I}
           in
              if DistKI < @Closest then
                 Closest := DistKI
                 ClosestPair := YS.K#YS.I
              end
           end
        end
        @Closest#@ClosestPair
     end
  end

  %% To access components when points are represented as pairs
  X = 1
  Y = 2

  %% returns a less-than predicate that accesses feature F
  fun {LessThanBy F}
     fun {$ A B}
        A.F < B.F
     end
  end

  fun {Random Min Max}
     Min +
     {Int.toFloat {OS.rand}} * (Max-Min)
     / {Int.toFloat {OS.randLimits _}}
  end

  fun {RandomPoint}
     {Random 0.0 100.0}#{Random 0.0 100.0}
  end

  Points = {MakeList 5}
in
  {ForAll Points RandomPoint}
  {Show Points}
  {Show {ClosestPair Points}}


program closestPoints;
{$IFDEF FPC}
   {$MODE Delphi}
{$ENDIF}
const
  PointCnt = 10000;//31623;
type
  TdblPoint = Record
               ptX,
               ptY : double;
              end;
  tPtLst =  array of TdblPoint;

  tMinDIstIdx  = record
                   md1,
                   md2 : NativeInt;
                 end;

function ClosPointBruteForce(var  ptl :tPtLst):tMinDIstIdx;
Var
  i,j,k : NativeInt;
  mindst2,dst2: double; //square of distance, no need to sqrt
  p0,p1 : ^TdblPoint;   //using pointer, since calc of ptl[?] takes much time
Begin
  i := Low(ptl);
  j := High(ptl);
  result.md1 := i;result.md2 := j;
  mindst2 := sqr(ptl[i].ptX-ptl[j].ptX)+sqr(ptl[i].ptY-ptl[j].ptY);
  repeat
    p0 := @ptl[i];
    p1 := p0; inc(p1);
    For k := i+1 to j do
    Begin
      dst2:= sqr(p0^.ptX-p1^.ptX)+sqr(p0^.ptY-p1^.ptY);
      IF mindst2 > dst2  then
      Begin
        mindst2 :=  dst2;
        result.md1 := i;
        result.md2 := k;
      end;
      inc(p1);
    end;
    inc(i);
  until i = j;
end;

var
  PointLst :tPtLst;
  cloPt : tMinDIstIdx;
  i : NativeInt;
Begin
  randomize;
  setlength(PointLst,PointCnt);
  For i := 0 to PointCnt-1 do
    with PointLst[i] do
    Begin
      ptX := random;
      ptY := random;
    end;
  cloPt:=  ClosPointBruteForce(PointLst) ;
  i := cloPt.md1;
  Writeln('P[',i:4,']= x: ',PointLst[i].ptX:0:8,
                     ' y: ',PointLst[i].ptY:0:8);
  i := cloPt.md2;
  Writeln('P[',i:4,']= x: ',PointLst[i].ptX:0:8,
                     ' y: ',PointLst[i].ptY:0:8);
end.


use strict;
use warnings;
use POSIX qw(ceil);

sub dist {
   my ($a, $b) = @_;
   return sqrt(($a->[0] - $b->[0])**2 +
               ($a->[1] - $b->[1])**2)
}

sub closest_pair_simple {
    my @points = @{ shift @_ };
    my ($a, $b, $d) = ( $points[0], $points[1], dist($points[0], $points[1]) );
    while( @points ) {
        my $p = pop @points;
        for my $l (@points) {
            my $t = dist($p, $l);
            ($a, $b, $d) = ($p, $l, $t) if $t < $d;
        }
    }
    $a, $b, $d
}

sub closest_pair {
   my @r = @{ shift @_ };
   closest_pair_real( [sort { $a->[0] <=> $b->[0] } @r], [sort { $a->[1] <=> $b->[1] } @r] )
}

sub closest_pair_real {
    my ($rx, $ry) = @_;
    return closest_pair_simple($rx) if scalar(@$rx) <= 3;

    my(@yR, @yL, @yS);
    my $N = @$rx;
    my $midx = ceil($N/2)-1;
    my @PL = @$rx[      0 .. $midx];
    my @PR = @$rx[$midx+1 .. $N-1];
    my $xm = $$rx[$midx]->[0];
    $_->[0] <= $xm ? push @yR, $_ : push @yL, $_ for @$ry;
    my ($al, $bl, $dL) = closest_pair_real(\@PL, \@yR);
    my ($ar, $br, $dR) = closest_pair_real(\@PR, \@yL);
    my ($w1, $w2, $closest) = $dR > $dL ? ($al, $bl, $dL) : ($ar, $br, $dR);
    abs($xm - $_->[0]) < $closest and push @yS, $_ for @$ry;

    for my $i (0 .. @yS-1) {
        my $k = $i + 1;
        while ( $k <= $#yS and ($yS[$k]->[1] - $yS[$i]->[1]) < $closest ) {
            my $d = dist($yS[$k], $yS[$i]);
            ($w1, $w2, $closest) = ($yS[$k], $yS[$i], $d) if $d < $closest;
            $k++;
        }
    }
    $w1, $w2, $closest
}

my @points;
push @points, [rand(20)-10, rand(20)-10] for 1..5000;
printf "%.8f between (%.5f, %.5f), (%.5f, %.5f)\n", $_->[2], @{$$_[0]}, @{$$_[1]}
    for [closest_pair_simple(\@points)], [closest_pair(\@points)];


with javascript_semantics
function bruteForceClosestPair(sequence s)
    atom {x1,y1} = s[1], {x2,y2} = s[2],
         dx = x1-x2, dy = y1-y2,
         mind = dx*dx+dy*dy
    sequence minp = s[1..2]
    for i=1 to length(s)-1 do
        {x1,y1} = s[i]
        for j=i+1 to length(s) do
            {x2,y2} = s[j]
            dx = x1-x2
            dx = dx*dx
            if dx<mind then
                dy = y1-y2
                dx += dy*dy
                if dx<mind then
                    mind = dx
                    minp = {s[i],s[j]}
                end if
            end if
        end for
    end for
    return {sqrt(mind),minp}
end function

sequence testset = sq_rnd(repeat({1,1},10000))
atom t0 = time()
{atom d, sequence points} = bruteForceClosestPair(testset)
-- (Sorting the final point pair makes brute/dc more likely to tally. Note however
--  when >1 equidistant pairs exist, brute and dc may well return different pairs;
--  it is only a problem if they decide to return different minimum distances.)
atom {{x1,y1},{x2,y2}} = sort(deep_copy(points))
printf(1,"Closest pair: {%f,%f} {%f,%f}, distance=%f (%3.2fs)\n",{x1,y2,x2,y2,d,time()-t0})

t0 = time()
constant X = 1, Y = 2
sequence xP = sort(deep_copy(testset))

function byY(sequence p1, p2)
    return compare(p1[Y],p2[Y])
end function
sequence yP = custom_sort(routine_id("byY"),deep_copy(testset))

function distsq(sequence p1,p2)
    atom {x1,y1} = p1, {x2,y2} = p2
    x1 -= x2
    y1 -= y2
    return x1*x1 + y1*y1
end function

function closestPair(sequence xP, yP)
-- where xP is P(1) .. P(N) sorted by x coordinate, and
--       yP is P(1) .. P(N) sorted by y coordinate (ascending order)
    integer N = length(xP),
         midN = floor(N/2)
    assert(length(yP)=N)
    if N<=3 then
        return bruteForceClosestPair(xP)
    end if
    sequence xL = xP[1..midN],
             xR = xP[midN+1..N],
             yL = {},
             yR = {}
    atom xm = xP[midN][X]
    for i=1 to N do
        if yP[i][X]<=xm then
            yL = append(yL,yP[i])
        else
            yR = append(yR,yP[i])
        end if
    end for
    {atom dL, sequence pairL} = closestPair(xL, yL)
    {atom dR, sequence pairR} = closestPair(xR, yR)
    {atom dmin, sequence pairMin} = min({dL, pairL},{dR, pairR})
    sequence yS = {}
    for i=1 to length(yP) do
        if abs(xm-yP[i][X])<dmin then
            yS = append(yS,yP[i])
        end if
    end for
    integer nS = length(yS)
    {atom closest, sequence cPair} = {dmin*dmin, pairMin}
    for i=1 to nS-1 do
        integer k = i + 1
        while k<=nS and (yS[k][Y]-yS[i][Y])<dmin do
            d = distsq(yS[k],yS[i])
            if d<closest then
                {closest, cPair} = {d, {yS[k], yS[i]}}
            end if
            k += 1
        end while
    end for
    return {sqrt(closest), cPair}
end function

{d,points} = closestPair(xP,yP)
{{x1,y1},{x2,y2}} = sort(deep_copy(points)) -- (see note above)
printf(1,"Closest pair: {%f,%f} {%f,%f}, distance=%f (%3.2fs)\n",{x1,y2,x2,y2,d,time()-t0})


(de closestPairBF (Lst)
   (let Min T
      (use (Pt1 Pt2)
         (for P Lst
            (for Q Lst
               (or
                  (== P Q)
                  (>=
                     (setq N
                        (let (A (- (car P) (car Q))  B (- (cdr P) (cdr Q)))
                           (+ (* A A) (* B B)) ) )
                     Min )
                  (setq Min N  Pt1 P  Pt2 Q) ) ) )
         (list Pt1 Pt2 (sqrt Min)) ) ) )


/* Closest Pair Problem */
closest: procedure options (main);
   declare n fixed binary;

   get list (n);
   begin;
      declare 1 P(n),
               2 x float,
               2 y float;
      declare (i, ii, j, jj) fixed binary;
      declare (distance, min_distance initial (0) ) float;

      get list (P);
      min_distance = sqrt( (P.x(1) - P.x(2))**2 + (P.y(1) - P.y(2))**2 );
      ii = 1;  jj = 2;
      do i = 1 to n;
         do j = 1 to n;
            distance = sqrt( (P.x(i) - P.x(j))**2 + (P.y(i) - P.y(j))**2 );
            if distance > 0 then
             if distance < min_distance  then
               do;
                  min_distance = distance;
                  ii = i; jj = j;
               end;
         end;
      end;
      put skip edit ('The minimum distance ', min_distance,
                     ' is between the points [', P.x(ii),
                     ',', P.y(ii), '] and [', P.x(jj), ',', P.y(jj), ']' )
                     (a, f(6,2));
   end;
end closest;


% 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.


Procedure.d bruteForceClosestPair(Array P.coordinate(1))
  Protected N=ArraySize(P()), i, j
  Protected mindistance.f=Infinity(), t.d
  Shared a, b
  If N<2
    a=0: b=0
  Else
    For i=0 To N-1
      For j=i+1 To N
        t=Pow(Pow(P(i)\x-P(j)\x,2)+Pow(P(i)\y-P(j)\y,2),0.5)
        If mindistance>t
          mindistance=t
          a=i: b=j
        EndIf
      Next
    Next
  EndIf
  ProcedureReturn mindistance
EndProcedure


"""
  Compute nearest pair of points using two algorithms

  First algorithm is 'brute force' comparison of every possible pair.
  Second, 'divide and conquer', is based on:
    www.cs.iupui.edu/~xkzou/teaching/CS580/Divide-and-conquer-closestPair.ppt
"""

from random import randint, randrange
from operator import itemgetter, attrgetter

infinity = float('inf')

# Note the use of complex numbers to represent 2D points making distance == abs(P1-P2)

def bruteForceClosestPair(point):
    numPoints = len(point)
    if numPoints < 2:
        return infinity, (None, None)
    return min( ((abs(point[i] - point[j]), (point[i], point[j]))
                 for i in range(numPoints-1)
                 for j in range(i+1,numPoints)),
                key=itemgetter(0))

def closestPair(point):
    xP = sorted(point, key= attrgetter('real'))
    yP = sorted(point, key= attrgetter('imag'))
    return _closestPair(xP, yP)

def _closestPair(xP, yP):
    numPoints = len(xP)
    if numPoints <= 3:
        return bruteForceClosestPair(xP)
    Pl = xP[:numPoints/2]
    Pr = xP[numPoints/2:]
    Yl, Yr = [], []
    xDivider = Pl[-1].real
    for p in yP:
        if p.real <= xDivider:
            Yl.append(p)
        else:
            Yr.append(p)
    dl, pairl = _closestPair(Pl, Yl)
    dr, pairr = _closestPair(Pr, Yr)
    dm, pairm = (dl, pairl) if dl < dr else (dr, pairr)
    # Points within dm of xDivider sorted by Y coord
    closeY = [p for p in yP  if abs(p.real - xDivider) < dm]
    numCloseY = len(closeY)
    if numCloseY > 1:
        # There is a proof that you only need compare a max of 7 next points
        closestY = min( ((abs(closeY[i] - closeY[j]), (closeY[i], closeY[j]))
                         for i in range(numCloseY-1)
                         for j in range(i+1,min(i+8, numCloseY))),
                        key=itemgetter(0))
        return (dm, pairm) if dm <= closestY[0] else closestY
    else:
        return dm, pairm

def times():
    ''' Time the different functions
    '''
    import timeit

    functions = [bruteForceClosestPair, closestPair]
    for f in functions:
        print 'Time for', f.__name__, timeit.Timer(
            '%s(pointList)' % f.__name__,
            'from closestpair import %s, pointList' % f.__name__).timeit(number=1)

pointList = [randint(0,1000)+1j*randint(0,1000) for i in range(2000)]

if __name__ == '__main__':
    pointList = [(5+9j), (9+3j), (2+0j), (8+4j), (7+4j), (9+10j), (1+9j), (8+2j), 10j, (9+6j)]
    print pointList
    print '  bruteForceClosestPair:', bruteForceClosestPair(pointList)
    print '            closestPair:', closestPair(pointList)
    for i in range(10):
        pointList = [randrange(11)+1j*randrange(11) for i in range(10)]
        print '\n', pointList
        print ' bruteForceClosestPair:', bruteForceClosestPair(pointList)
        print '           closestPair:', closestPair(pointList)
    print '\n'
    times()
    times()
    times()


closest_pair_brute <-function(x,y,plotxy=F) {
    xy = cbind(x,y)
    cp = bruteforce(xy)
    cat("\n\nShortest path found = \n From:\t\t(",cp[1],',',cp[2],")\n To:\t\t(",cp[3],',',cp[4],")\n Distance:\t",cp[5],"\n\n",sep="")
    if(plotxy) {
        plot(x,y,pch=19,col='black',main="Closest Pair", asp=1)
        points(cp[1],cp[2],pch=19,col='red')
        points(cp[3],cp[4],pch=19,col='red')
    }
    distance <- function(p1,p2) {
        x1 = (p1[1])
        y1 = (p1[2])
        x2 = (p2[1])
        y2 = (p2[2])
        sqrt((x2-x1)^2 + (y2-y1)^2)
    }
    bf_iter <- function(m,p,idx=NA,d=NA,n=1) {
        dd = distance(p,m[n,])
        if((is.na(d) || dd<=d) && p!=m[n,]){d = dd; idx=n;}
        if(n == length(m[,1])) { c(m[idx,],d) }
        else bf_iter(m,p,idx,d,n+1)
    }
    bruteforce <- function(pmatrix,n=1,pd=c(NA,NA,NA,NA,NA)) {
        p = pmatrix[n,]
        ppd = c(p,bf_iter(pmatrix,p))
        if(ppd[5]<pd[5] || is.na(pd[5])) pd = ppd
        if(n==length(pmatrix[,1]))  pd
        else bruteforce(pmatrix,n+1,pd)
    }
}


#lang racket
(define (dist z0 z1) (magnitude (- z1 z0)))
(define (dist* zs)  (apply dist zs))

(define (closest-pair zs)
  (if (< (length zs) 2)
      -inf.0
      (first
       (sort (for/list ([z0 zs])
               (list z0 (argmin (λ(z) (if (= z z0) +inf.0 (dist z z0))) zs)))
             < #:key dist*))))

(define result (closest-pair '(0+1i 1+2i 3+4i)))
(displayln (~a "Closest points: " result))
(displayln (~a "Distance: " (dist* result)))


sub MAIN ($N = 5000) {
    my @points = (^$N).map: { [rand × 20 - 10, rand × 20 - 10] }
    printf "%.8f between (%.5f, %.5f), (%.5f, %.5f)\n", $_[2], @($_[1]), @($_[0]) for
        closest-pair(@points), closest-pair-simple(@points)
}

sub dist-squared(@a, @b) { (@a[0] - @b[0])² + (@a[1] - @b[1])² }

sub closest-pair-simple(@points is copy) {
    return ∞ if @points < 2;
    my ($a, $b, $d) = |@points[0,1], dist-squared(|@points[0,1]);
    while @points {
        my \p = pop @points;
        for @points -> \l {
            ($a, $b, $d) = p, l, $_ if $_ < $d given dist-squared(p, l);
        }
    }
    $a, $b, $d.sqrt
}

sub closest-pair(@r) {
    closest-pair-real (@r.sort: *.[0]), (@r.sort: *.[1])
}

sub closest-pair-real(@rx, @ry) {
    return closest-pair-simple(@rx) if @rx ≤ 3;

    my \N  = @rx;
    my \midx = ceiling(N/2) - 1;
    my @PL := @rx[     0 ..  midx];
    my @PR := @rx[midx+1 ..^ N   ];
    my \xm  = @rx[midx;0];
    (.[0] ≤ xm ?? my @yR !! my @yL).push: @$_ for @ry;
    my (\al, \bl, \dL) = closest-pair-real(@PL, @yR);
    my (\ar, \br, \dR) = closest-pair-real(@PR, @yL);
    my ($w1, $w2, $closest) = dR < dL ?? (ar, br, dR) !! (al, bl, dL);
    my @yS = @ry.grep: { (xm - .[0]).abs < $closest }

    for 0 ..^ @yS -> \i {
        for i+1 ..^ @yS -> \k {
            next unless @yS[k;1] - @yS[i;1] < $closest;
            ($w1, $w2, $closest) = |@yS[k, i], $_ if $_ < $closest given dist-squared(|@yS[k, i]).sqrt;
        }
    }
    $w1, $w2, $closest
}


/*REXX program  solves the   closest pair   of  points  problem  (in two dimensions).   */
parse arg N LO HI seed .                         /*obtain optional arguments from the CL*/
if  N=='' |  N==","  then  N=   100              /*Not specified?  Then use the default.*/
if LO=='' | LO==","  then LO=     0              /* "      "         "   "   "     "    */
if HI=='' | HI==","  then HI= 20000              /* "      "         "   "   "     "    */
if datatype(seed, 'W')   then call random ,,seed /*seed for RANDOM (BIF)  repeatability.*/
w= length(HI);     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(LO, HI)     /*    "    a    "     X   */
   /*╚══════════════════════╝*/      @y.j= random(LO, HI)     /*    "    a    "     Y   */
                                     end   /*j*/              /*X  &  Y  make the point.*/
          A= 1;  B= 2                            /* [↓]  MIND  is actually the squared  */
minD= (@x.A - @x.B)**2   +   (@y.A - @y.B)**2    /* distance between the 1st two points.*/
                                                 /* [↓]  use of XJ & YJ speed things up.*/
    do   j=1    for N-1;  xj= @x.j;   yj= @y.j   /*find min distance between a point ···*/
      do k=j+1  for N-j-1                        /*  ··· and all other (higher) points. */
      sd= (xj - @x.k)**2   +   (yj - @y.k)**2    /*compute squared distance from points.*/
      if sd<minD  then parse  value     sd  j  k      with      minD  A  B
      end   /*k*/                                /* [↑]  needn't take SQRT of SD  (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(minD)) / 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 0                                           /*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


Point = Struct.new(:x, :y)

def distance(p1, p2)
  Math.hypot(p1.x - p2.x, p1.y - p2.y)
end

def closest_bruteforce(points)
  mindist, minpts = Float::MAX, []
  points.combination(2) do |pi,pj|
    dist = distance(pi, pj)
    if dist < mindist
      mindist = dist
      minpts = [pi, pj]
    end
  end
  [mindist, minpts]
end

def closest_recursive(points)
  return closest_bruteforce(points) if points.length <= 3
  xP = points.sort_by(&:x)
  mid = points.length / 2
  xm = xP[mid].x
  dL, pairL = closest_recursive(xP[0,mid])
  dR, pairR = closest_recursive(xP[mid..-1])
  dmin, dpair = dL<dR ? [dL, pairL] : [dR, pairR]
  yP = xP.find_all {|p| (xm - p.x).abs < dmin}.sort_by(&:y)
  closest, closestPair = dmin, dpair
  0.upto(yP.length - 2) do |i|
    (i+1).upto(yP.length - 1) do |k|
      break if (yP[k].y - yP[i].y) >= dmin
      dist = distance(yP[i], yP[k])
      if dist < closest
        closest = dist
        closestPair = [yP[i], yP[k]]
      end
    end
  end
  [closest, closestPair]
end

points = Array.new(100) {Point.new(rand, rand)}
p ans1 = closest_bruteforce(points)
p ans2 = closest_recursive(points)
fail "bogus!" if ans1[0] != ans2[0]

require 'benchmark'

points = Array.new(10000) {Point.new(rand, rand)}
Benchmark.bm(12) do |x|
  x.report("bruteforce") {ans1 = closest_bruteforce(points)}
  x.report("recursive")  {ans2 = closest_recursive(points)}
end


//! We interpret complex numbers as points in the Cartesian plane, here. We also use the
//! [sweepline/plane sweep closest pairs algorithm][algorithm] instead of the divide-and-conquer
//! algorithm, since it's (arguably) easier to implement, and an efficient implementation does not
//! require use of unsafe.
//!
//! [algorithm]: http://www.cs.mcgill.ca/~cs251/ClosestPair/ClosestPairPS.html
extern crate num;

use num::complex::Complex;
use std::cmp::{Ordering, PartialOrd};
use std::collections::BTreeSet;
type Point = Complex<f32>;

/// Wrapper around `Point` (i.e. `Complex<f32>`) so that we can use a `TreeSet`
#[derive(PartialEq)]
struct YSortedPoint {
    point: Point,
}

impl PartialOrd for YSortedPoint {
    fn partial_cmp(&self, other: &YSortedPoint) -> Option<Ordering> {
        (self.point.im, self.point.re).partial_cmp(&(other.point.im, other.point.re))
    }
}

impl Ord for YSortedPoint {
    fn cmp(&self, other: &YSortedPoint) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl Eq for YSortedPoint {}

fn closest_pair(points: &mut [Point]) -> Option<(Point, Point)> {
    if points.len() < 2 {
        return None;
    }

    points.sort_by(|a, b| (a.re, a.im).partial_cmp(&(b.re, b.im)).unwrap());

    let mut closest_pair = (points[0], points[1]);
    let mut closest_distance_sqr = (points[0] - points[1]).norm_sqr();
    let mut closest_distance = closest_distance_sqr.sqrt();

    // the strip that we inspect for closest pairs as we sweep right
    let mut strip: BTreeSet<YSortedPoint> = BTreeSet::new();
    strip.insert(YSortedPoint { point: points[0] });
    strip.insert(YSortedPoint { point: points[1] });

    // index of the leftmost point on the strip (on points)
    let mut leftmost_idx = 0;

    // Start the sweep!
    for (idx, point) in points.iter().enumerate().skip(2) {
        // Remove all points farther than `closest_distance` away from `point`
        // along the x-axis
        while leftmost_idx < idx {
            let leftmost_point = &points[leftmost_idx];
            if (leftmost_point.re - point.re).powi(2) < closest_distance_sqr {
                break;
            }
            strip.remove(&YSortedPoint {
                point: *leftmost_point,
            });
            leftmost_idx += 1;
        }

        // Compare to points in bounding box
        {
            let low_bound = YSortedPoint {
                point: Point {
                    re: ::std::f32::INFINITY,
                    im: point.im - closest_distance,
                },
            };
            let mut strip_iter = strip.iter().skip_while(|&p| p < &low_bound);
            loop {
                let point2 = match strip_iter.next() {
                    None => break,
                    Some(p) => p.point,
                };
                if point2.im - point.im >= closest_distance {
                    // we've reached the end of the box
                    break;
                }
                let dist_sqr = (*point - point2).norm_sqr();
                if dist_sqr < closest_distance_sqr {
                    closest_pair = (point2, *point);
                    closest_distance_sqr = dist_sqr;
                    closest_distance = dist_sqr.sqrt();
                }
            }
        }

        // Insert point into strip
        strip.insert(YSortedPoint { point: *point });
    }

    Some(closest_pair)
}

pub fn main() {
    let mut test_data = [
        Complex::new(0.654682, 0.925557),
        Complex::new(0.409382, 0.619391),
        Complex::new(0.891663, 0.888594),
        Complex::new(0.716629, 0.996200),
        Complex::new(0.477721, 0.946355),
        Complex::new(0.925092, 0.818220),
        Complex::new(0.624291, 0.142924),
        Complex::new(0.211332, 0.221507),
        Complex::new(0.293786, 0.691701),
        Complex::new(0.839186, 0.728260),
    ];
    let (p1, p2) = closest_pair(&mut test_data[..]).unwrap();
    println!("Closest pair: {} and {}", p1, p2);
    println!("Distance: {}", (p1 - p2).norm_sqr().sqrt());
}


import scala.collection.mutable.ListBuffer
import scala.util.Random

object ClosestPair {
  case class Point(x: Double, y: Double){
    def distance(p: Point) = math.hypot(x-p.x, y-p.y)

    override def toString = "(" + x + ", " + y + ")"
  }

  case class Pair(point1: Point, point2: Point) {
    val distance: Double = point1 distance point2

    override def toString = {
      point1 + "-" + point2 + " : " + distance
    }
  }

  def sortByX(points: List[Point]) = {
    points.sortBy(point => point.x)
  }

  def sortByY(points: List[Point]) = {
    points.sortBy(point => point.y)
  }

  def divideAndConquer(points: List[Point]): Pair = {
    val pointsSortedByX = sortByX(points)
    val pointsSortedByY = sortByY(points)

    divideAndConquer(pointsSortedByX, pointsSortedByY)
  }

  def bruteForce(points: List[Point]): Pair = {
    val numPoints = points.size
    if (numPoints < 2)
      return null
    var pair = Pair(points(0), points(1))
    if (numPoints > 2) {
      for (i <- 0 until numPoints - 1) {
        val point1 = points(i)
        for (j <- i + 1 until numPoints) {
          val point2 = points(j)
          val distance = point1 distance point2
          if (distance < pair.distance)
            pair = Pair(point1, point2)
        }
      }
    }
    return pair
  }

  private def divideAndConquer(pointsSortedByX: List[Point], pointsSortedByY: List[Point]): Pair = {
    val numPoints = pointsSortedByX.size
    if(numPoints <= 3) {
      return bruteForce(pointsSortedByX)
    }

    val dividingIndex = numPoints >>> 1
    val leftOfCenter = pointsSortedByX.slice(0, dividingIndex)
    val rightOfCenter = pointsSortedByX.slice(dividingIndex, numPoints)

    var tempList = leftOfCenter.map(x => x)
    //println(tempList)
    tempList = sortByY(tempList)
    var closestPair = divideAndConquer(leftOfCenter, tempList)

    tempList = rightOfCenter.map(x => x)
    tempList = sortByY(tempList)

    val closestPairRight = divideAndConquer(rightOfCenter, tempList)

    if (closestPairRight.distance < closestPair.distance)
      closestPair = closestPairRight

    tempList = List[Point]()
    val shortestDistance = closestPair.distance
    val centerX = rightOfCenter(0).x

    for (point <- pointsSortedByY) {
      if (Math.abs(centerX - point.x) < shortestDistance)
        tempList = tempList :+ point
    }

    closestPair = shortestDistanceF(tempList, shortestDistance, closestPair)
    closestPair
  }

  private def shortestDistanceF(tempList: List[Point], shortestDistance: Double, closestPair: Pair ): Pair = {
    var shortest = shortestDistance
    var bestResult = closestPair
    for (i <- 0 until tempList.size) {
      val point1 = tempList(i)
      for (j <- i + 1 until tempList.size) {
        val point2 = tempList(j)
        if ((point2.y - point1.y) >= shortestDistance)
          return closestPair
        val distance = point1 distance point2
        if (distance < closestPair.distance)
        {
          bestResult = Pair(point1, point2)
          shortest = distance
        }
      }
    }

    closestPair
  }

  def main(args: Array[String]) {
    val numPoints = if(args.length == 0) 1000 else args(0).toInt

    val points = ListBuffer[Point]()
    val r = new Random()
    for (i <- 0 until numPoints) {
      points.+=:(new Point(r.nextDouble(), r.nextDouble()))
    }
    println("Generated " + numPoints + " random points")

    var startTime = System.currentTimeMillis()
    val bruteForceClosestPair = bruteForce(points.toList)
    var elapsedTime = System.currentTimeMillis() - startTime
    println("Brute force (" + elapsedTime + " ms): " + bruteForceClosestPair)

    startTime = System.currentTimeMillis()
    val dqClosestPair = divideAndConquer(points.toList)
    elapsedTime = System.currentTimeMillis() - startTime
    println("Divide and conquer (" + elapsedTime + " ms): " + dqClosestPair)
    if (bruteForceClosestPair.distance != dqClosestPair.distance)
      println("MISMATCH")
  }
}


const type: point is new struct
    var float: x is 0.0;
    var float: y is 0.0;
  end struct;

const func float: distance (in point: p1, in point: p2) is
  return sqrt((p1.x-p2.x)**2+(p1.y-p2.y)**2);

const func array point: closest_pair (in array point: points) is func
  result
    var array point: result is 0 times point.value;
  local
    var float: dist is 0.0;
    var float: minDistance is Infinity;
    var integer: i is 0;
    var integer: j is 0;
    var integer: savei is 0;
    var integer: savej is 0;
  begin
    for i range 1 to pred(length(points)) do
      for j range succ(i) to length(points) do
        dist := distance(points[i], points[j]);
        if dist < minDistance then
          minDistance := dist;
          savei := i;
          savej := j;
        end if;
      end for;
    end for;
    if minDistance <> Infinity then
      result := [] (points[savei], points[savej]);
    end if;
  end func;


func dist_squared(a, b) {
    sqr(a[0] - b[0]) + sqr(a[1] - b[1])
}

func closest_pair_simple(arr) {
    arr.len < 2 && return Inf
    var (a, b, d) = (arr[0, 1], dist_squared(arr[0,1]))
    arr.clone!
    while (arr) {
        var p = arr.pop
        for l in arr {
            var t = dist_squared(p, l)
            if (t < d) {
                (a, b, d) = (p, l, t)
            }
        }
    }
    return(a, b, d.sqrt)
}

func closest_pair_real(rx, ry) {
    rx.len <= 3 && return closest_pair_simple(rx)

    var N = rx.len
    var midx = (ceil(N/2)-1)
    var (PL, PR) = rx.part(midx)

    var xm = rx[midx][0]

    var yR = []
    var yL = []

    for item in ry {
        (item[0] <= xm ? yR : yL) << item
    }

    var (al, bl, dL) = closest_pair_real(PL, yR)
    var (ar, br, dR) = closest_pair_real(PR, yL)

    al == Inf && return (ar, br, dR)
    ar == Inf && return (al, bl, dL)

    var (m1, m2, dmin) = (dR < dL ? [ar, br, dR]...
                                  : [al, bl, dL]...)

    var yS = ry.grep { |a| abs(xm - a[0]) < dmin }

    var (w1, w2, closest) = (m1, m2, dmin)
    for i in (0 ..^ yS.end) {
        for k in (i+1 .. yS.end) {
            yS[k][1] - yS[i][1] < dmin || break
            var d = dist_squared(yS[k], yS[i]).sqrt
            if (d < closest) {
                (w1, w2, closest) = (yS[k], yS[i], d)
            }
        }
    }

    return (w1, w2, closest)
}

func closest_pair(r) {
    var ax = r.sort_by { |a| a[0] }
    var ay = r.sort_by { |a| a[1] }
    return closest_pair_real(ax, ay);
}

var N = 5000
var points = N.of { [1.rand*20 - 10, 1.rand*20 - 10] }
var (af, bf, df) = closest_pair(points)
say "#{df} at (#{af.join(' ')}), (#{bf.join(' ')})"


import Foundation

struct Point {
  var x: Double
  var y: Double

  func distance(to p: Point) -> Double {
    let x = pow(p.x - self.x, 2)
    let y = pow(p.y - self.y, 2)

    return (x + y).squareRoot()
  }
}

extension Collection where Element == Point {
  func closestPair() -> (Point, Point)? {
    let (xP, xY) = (sorted(by: { $0.x < $1.x }), sorted(by: { $0.y < $1.y }))

    return Self.closestPair(xP, xY)?.1
  }

  static func closestPair(_ xP: [Element], _ yP: [Element]) -> (Double, (Point, Point))? {
    guard xP.count > 3 else { return xP.closestPairBruteForce() }

    let half = xP.count / 2
    let xl = Array(xP[..<half])
    let xr = Array(xP[half...])
    let xm = xl.last!.x
    let (yl, yr) = yP.reduce(into: ([Element](), [Element]()), {cur, el in
      if el.x > xm {
        cur.1.append(el)
      } else {
        cur.0.append(el)
      }
    })

    guard let (distanceL, pairL) = closestPair(xl, yl) else { return nil }
    guard let (distanceR, pairR) = closestPair(xr, yr) else { return nil }

    let (dMin, pairMin) = distanceL > distanceR ? (distanceR, pairR) : (distanceL, pairL)

    let ys = yP.filter({ abs(xm - $0.x) < dMin })

    var (closest, pairClosest) = (dMin, pairMin)

    for i in 0..<ys.count {
      let p1 = ys[i]

      for k in i+1..<ys.count {
        let p2 = ys[k]

        guard abs(p2.y - p1.y) < dMin else { break }

        let distance = abs(p1.distance(to: p2))

        if distance < closest {
          (closest, pairClosest) = (distance, (p1, p2))
        }
      }
    }

    return (closest, pairClosest)
  }

  func closestPairBruteForce() -> (Double, (Point, Point))? {
    guard count >= 2 else { return nil }

    var closestPoints = (self.first!, self[index(after: startIndex)])
    var minDistance = abs(closestPoints.0.distance(to: closestPoints.1))

    guard count != 2 else { return (minDistance, closestPoints) }

    for i in 0..<count {
      for j in i+1..<count {
        let (iIndex, jIndex) = (index(startIndex, offsetBy: i), index(startIndex, offsetBy: j))
        let (p1, p2) = (self[iIndex], self[jIndex])

        let distance = abs(p1.distance(to: p2))

        if distance < minDistance {
          minDistance = distance
          closestPoints = (p1, p2)
        }
      }
    }

    return (minDistance, closestPoints)
  }
}

var points = [Point]()

for _ in 0..<10_000 {
  points.append(Point(
    x: .random(in: -10.0...10.0),
    y: .random(in: -10.0...10.0)
  ))
}

print(points.closestPair()!)


package require Tcl 8.5

# retrieve the x-coordinate
proc x p {lindex $p 0}
# retrieve the y-coordinate
proc y p {lindex $p 1}

proc distance {p1 p2} {
    expr {hypot(([x $p1]-[x $p2]), ([y $p1]-[y $p2]))}
}

proc closest_bruteforce {points} {
    set n [llength $points]
    set mindist Inf
    set minpts {}
    for {set i 0} {$i < $n - 1} {incr i} {
        for {set j [expr {$i + 1}]} {$j < $n} {incr j} {
            set p1 [lindex $points $i]
            set p2 [lindex $points $j]
            set dist [distance $p1 $p2]
            if {$dist < $mindist} {
                set mindist $dist
                set minpts [list $p1 $p2]
            }
        }
    }
    return [list $mindist $minpts]
}

proc closest_recursive {points} {
    set n [llength $points]
    if {$n <= 3} {
        return [closest_bruteforce $points]
    }
    set xP [lsort -real -increasing -index 0 $points]
    set mid [expr {int(ceil($n/2.0))}]
    set PL [lrange $xP 0 [expr {$mid-1}]]
    set PR [lrange $xP $mid end]
    set procname [lindex [info level 0] 0]
    lassign [$procname $PL] dL pairL
    lassign [$procname $PR] dR pairR
    if {$dL < $dR} {
        set dmin $dL
        set dpair $pairL
    } else {
        set dmin $dR
        set dpair $pairR
    }

    set xM [x [lindex $PL end]]
    foreach p $xP {
        if {abs($xM - [x $p]) < $dmin} {
            lappend S $p
        }
    }
    set yP [lsort -real -increasing -index 1 $S]
    set closest Inf
    set nP [llength $yP]
    for {set i 0} {$i <= $nP-2} {incr i} {
        set yPi [lindex $yP $i]
        for {set k [expr {$i+1}]; set yPk [lindex $yP $k]} {
            $k < $nP-1 && ([y $yPk]-[y $yPi]) < $dmin
        } {incr k; set yPk [lindex $yP $k]} {
            set dist [distance $yPk $yPi]
            if {$dist < $closest} {
                set closest $dist
                set closestPair [list $yPi $yPk]
            }
        }
    }
    expr {$closest < $dmin ? [list $closest $closestPair] : [list $dmin $dpair]}
}

# testing
set N 10000
for {set i 1} {$i <= $N} {incr i} {
    lappend points [list [expr {rand()*100}] [expr {rand()*100}]]
}

# instrument the number of calls to [distance] to examine the
# efficiency of the recursive solution
trace add execution distance enter comparisons
proc comparisons args {incr ::comparisons}

puts [format "%-10s  %9s  %9s  %s" method compares time closest]
foreach method {bruteforce recursive} {
    set ::comparisons 0
    set time [time {set ::dist($method) [closest_$method $points]} 1]
    puts [format "%-10s  %9d  %9d  %s" $method $::comparisons [lindex $time 0] [lindex $::dist($method) 0]]
}


#import flo

clop = @iiK0 fleq$-&l+ *EZF ^\~& plus+ sqr~~+ minus~~bbI


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


CLOSE DATABASES ALL
CREATE CURSOR pairs(id I, xcoord B(6), ycoord B(6))
INSERT INTO pairs VALUES (1, 0.654682, 0.925557)
INSERT INTO pairs VALUES (2, 0.409382, 0.619391)
INSERT INTO pairs VALUES (3, 0.891663, 0.888594)
INSERT INTO pairs VALUES (4, 0.716629, 0.996200)
INSERT INTO pairs VALUES (5, 0.477721, 0.946355)
INSERT INTO pairs VALUES (6, 0.925092, 0.818220)
INSERT INTO pairs VALUES (7, 0.624291, 0.142924)
INSERT INTO pairs VALUES (8, 0.211332, 0.221507)
INSERT INTO pairs VALUES (9, 0.293786, 0.691701)
INSERT INTO pairs VALUES (10, 0.839186, 0.728260)

SELECT p1.id As id1, p2.id As id2, ;
(p1.xcoord-p2.xcoord)^2 + (p1.ycoord-p2.ycoord)^2 As dist2 ;
FROM pairs p1 JOIN pairs p2 ON p1.id < p2.id ORDER BY 3 INTO CURSOR tmp

GO TOP
? "Closest pair is " + TRANSFORM(id1) + " and " + TRANSFORM(id2) + "."
? "Distance is " + TRANSFORM(SQRT(dist2))


import "/math" for Math
import "/sort" for Sort

var distance = Fn.new { |p1, p2| Math.hypot(p1[0] - p2[0], p1[1] - p2[1]) }

var bruteForceClosestPair = Fn.new { |p|
    var n = p.count
    if (n < 2) Fiber.abort("There must be at least two points.")
    var minPoints = [p[0], p[1]]
    var minDistance = distance.call(p[0], p[1])
    for (i in 0...n-1) {
        for (j in i+1...n) {
            var dist = distance.call(p[i], p[j])
            if (dist < minDistance) {
                minDistance = dist
                minPoints = [p[i], p[j]]
            }
        }
    }
    return [minDistance, minPoints]
}

var optimizedClosestPair // recursive so pre-declare
optimizedClosestPair = Fn.new { |xP, yP|
    var n = xP.count
    if (n <= 3) return bruteForceClosestPair.call(xP)
    var hn = (n/2).floor
    var xL = xP.take(hn).toList
    var xR = xP.skip(hn).toList
    var xm = xP[hn-1][0]
    var yL = yP.where { |p| p[0] <= xm }.toList
    var yR = yP.where { |p| p[0] >  xm }.toList
    var ll = optimizedClosestPair.call(xL, yL)
    var dL = ll[0]
    var pairL = ll[1]
    var rr = optimizedClosestPair.call(xR, yR)
    var dR = rr[0]
    var pairR = rr[1]
    var dmin = dR
    var pairMin = pairR
    if (dL < dR) {
        dmin = dL
        pairMin = pairL
    }
    var yS = yP.where { |p| (xm - p[0]).abs < dmin }.toList
    var nS = yS.count
    var closest = dmin
    var closestPair = pairMin
    for (i in 0...nS-1) {
        var k = i + 1
        while (k < nS && (yS[k][1] - yS[i][1] < dmin)) {
            var dist = distance.call(yS[k], yS[i])
            if (dist < closest) {
                closest = dist
                closestPair = [yS[k], yS[i]]
            }
            k = k + 1
        }
    }
    return [closest, closestPair]
}

var points = [
    [ [5, 9], [9, 3], [2, 0], [8, 4], [7, 4], [9, 10], [1, 9], [8, 2], [0, 10], [9, 6] ],

    [
        [0.654682, 0.925557], [0.409382, 0.619391], [0.891663, 0.888594],
        [0.716629, 0.996200], [0.477721, 0.946355], [0.925092, 0.818220],
        [0.624291, 0.142924], [0.211332, 0.221507], [0.293786, 0.691701],
        [0.839186, 0.728260]
    ]
]

for (p in points) {
    var dp = bruteForceClosestPair.call(p)
    var dist = dp[0]
    var pair = dp[1]
    System.print("Closest pair (brute force) is %(pair[0]) and %(pair[1]), distance %(dist)")
    var xP = Sort.merge(p) { |x, y| (x[0] - y[0]).sign }
    var yP = Sort.merge(p) { |x, y| (x[1] - y[1]).sign }
    dp = optimizedClosestPair.call(xP, yP)
    dist = dp[0]
    pair = dp[1]
    System.print("Closest pair (optimized)   is %(pair[0]) and %(pair[1]), distance %(dist)\n")
}


class Point{
   fcn init(_x,_y){ var[const] x=_x, y=_y; }
   fcn distance(p){ (p.x-x).hypot(p.y-y) }
   fcn toString   { String("Point(",x,",",y,")") }
}

   // find closest two points using brute ugly force:
   // find all combinations of two points, measure distance, pick smallest
fcn closestPoints(points){
   pairs:=Utils.Helpers.pickNFrom(2,points);
   triples:=pairs.apply(fcn([(p1,p2)]){ T(p1,p2,p1.distance(p2)) });
   triples.reduce(fcn([(_,_,d1)]p1,[(_,_,d2)]p2){
      if(d1 < d2) p1 else p2
   });
}


T Circle
   Float x, y, r

   F String()
      R ‘Circle(x=#.6, y=#.6, r=#.6)’.format(.x, .y, .r)

   F (x, y, r)
      .x = x
      .y = y
      .r = r

T Error
   String msg
   F (msg)
      .msg = msg

F circles_from_p1p2r(p1, p2, r)
   ‘Following explanation at http://mathforum.org/library/drmath/view/53027.html’
   I r == 0.0
      X Error(‘radius of zero’)
   V (x1, y1) = p1
   V (x2, y2) = p2
   I p1 == p2
      X Error(‘coincident points gives infinite number of Circles’)
   V (dx, dy) = (x2 - x1, y2 - y1)
   V q = sqrt(dx ^ 2 + dy ^ 2)
   I q > 2.0 * r
      X Error(‘separation of points > diameter’)
   V (x3, y3) = ((x1 + x2) / 2, (y1 + y2) / 2)
   V d = sqrt(r ^ 2 - (q / 2) ^ 2)
   V c1 = Circle(x' x3 - d * dy / q,
                 y' y3 + d * dx / q,
                 r' abs(r))
   V c2 = Circle(x' x3 + d * dy / q,
                 y' y3 - d * dx / q,
                 r' abs(r))
   R (c1, c2)

L(p1, p2, r) [((0.1234, 0.9876), (0.8765, 0.2345), 2.0),
              ((0.0000, 2.0000), (0.0000, 0.0000), 1.0),
              ((0.1234, 0.9876), (0.1234, 0.9876), 2.0),
              ((0.1234, 0.9876), (0.8765, 0.2345), 0.5),
              ((0.1234, 0.9876), (0.1234, 0.9876), 0.0)]
   print("Through points:\n  #.,\n  #.\n  and radius #.6\nYou can construct the following circles:".format(p1, p2, r))
   X.try
      V (c1, c2) = circles_from_p1p2r(p1, p2, r)
      print("  #.\n  #.\n".format(c1, c2))
   X.catch Error v
      print("  ERROR: #.\n".format(v.msg))


INCLUDE "H6:REALMATH.ACT"

PROC Circles(CHAR ARRAY sx1,sy1,sx2,sy2,sr)
  REAL x1,y1,x2,y2,r,x,y,bx,by,pb,cb,xx,yy
  REAL two,tmp1,tmp2,tmp3

  ValR(sx1,x1) ValR(sy1,y1)
  ValR(sx2,x2) ValR(sy2,y2)
  ValR(sr,r)   IntToReal(2,two)

  Print("p1=(") PrintR(x1) Put(32)
  PrintR(y1) Print(") p2=(")
  PrintR(x2) Put(32) PrintR(y2)
  Print(") r=") PrintR(r) Print(" -> ")

  IF RealEqual(r,rzero) THEN
    PrintE("Radius is zero, no circles") PutE()
    RETURN
  FI

  RealSub(x2,x1,tmp1) ;tmp1=x2-x1
  RealDiv(tmp1,two,x) ;x=(x2-x1)/2

  RealSub(y2,y1,tmp1) ;tmp1=y2-y1
  RealDiv(tmp1,two,y) ;y=(y2-y1)/2

  RealAdd(x1,x,bx) ;bx=x1+x
  RealAdd(y1,y,by) ;bx=x1+x

  RealMult(x,x,tmp1)      ;tmp1=x^2
  RealMult(y,y,tmp2)      ;tmp2=y^2
  RealAdd(tmp1,tmp2,tmp3) ;tmp3=x^2+y^2
  Sqrt(tmp3,pb)           ;pb=sqrt(x^2+y^2)

  IF RealEqual(pb,rzero) THEN
    PrintE("Infinite circles")
  ELSEIF RealGreater(pb,r) THEN
    PrintE("Points are too far, no circles")
  ELSE
    RealMult(r,r,tmp1)      ;tmp1=r^2
    RealMult(pb,pb,tmp2)    ;tmp2=pb^2
    RealSub(tmp1,tmp2,tmp3) ;tmp3=r^2-pb^2
    Sqrt(tmp3,cb)           ;cb=sqrt(r^2-pb^2)

    RealMult(y,cb,tmp1) ;tmp1=y*cb
    RealDiv(tmp1,pb,xx) ;xx=y*cb/pb

    RealMult(x,cb,tmp1) ;tmp1=x*cb
    RealDiv(tmp1,pb,yy) ;yy=x*cb/pb

    RealSub(bx,xx,tmp1) ;tmp1=bx-xx
    Print("c1=(") PrintR(tmp1) Put(32)

    RealAdd(by,yy,tmp1) ;tmp1=by+yy
    PrintR(tmp1) Print(") c2=(")

    RealAdd(bx,xx,tmp1) ;tmp1=bx+xx
    PrintR(tmp1) Put(32)

    RealSub(by,yy,tmp1) ;tmp1=by-yy
    PrintR(tmp1) PrintE(")")
  FI
  PutE()
RETURN

PROC Main()
  Put(125) PutE() ;clear the screen
  MathInit()
  Circles("0.1234","0.9876","0.8765","0.2345","2.0")
  Circles("0.0000","2.0000","0.0000","0.0000","1.0")
  Circles("0.1234","0.9876","0.1234","0.9876","2.0")
  Circles("0.1234","0.9876","0.8765","0.2345","0.5")
  Circles("0.1234","0.9876","0.1234","0.9876","0.0")
RETURN


# represents a point                                                 #
MODE POINT = STRUCT( REAL x, REAL y );
# returns TRUE if p1 is the same point as p2, FALSE otherwise        #
OP = = ( POINT p1, POINT p2 )BOOL: x OF p1 = x OF p2 AND y OF p1 = y OF p2;

# represents a circle with centre c and radius r                     #
MODE CIRCLE = STRUCT( POINT c, REAL r );
# returns the difference in x-coordinate of two points               #
PRIO XDIFF = 5;
OP   XDIFF = ( POINT p1, POINT p2 )REAL: x OF p1 - x OF p2;
# returns the difference in y-coordinate of two points               #
PRIO YDIFF = 5;
OP   YDIFF = ( POINT p1, POINT p2 )REAL: y OF p1 - y OF p2;
# returns the distance between two points                            #
OP   -     = ( POINT p1, POINT p2 )REAL:
     BEGIN
        REAL x diff   = p1 XDIFF p2;
        REAL y diff   = p1 YDIFF p2;
        sqrt( ( x diff * xdiff ) + ( y diff * y diff ) )
     END; # - #
# generate a human-readable version of the circle c                  #
OP TOSTRING = ( CIRCLE c )STRING:
       ( "radius:"
       + fixed(      r OF c, -8, 4 )
       + " @("
       + fixed( x OF c OF c, -8, 4 )
       + ", "
       + fixed( y OF c OF c, -8, 4 )
       + ")"
       );

# modes to represent the results of the circles procedure ...        #
# infinite number of circles                                         #
MODE INFINITECIRCLES = STRUCT( STRING t, REAL r );
# two possible circles                                               #
MODE TWOCIRCLES      = STRUCT( CIRCLE a, CIRCLE b );
# one possible circle results in a CIRCLE                            #
# no possible circles                                                #
MODE NOCIRCLES       = STRUCT( STRING reason, POINT p1, POINT p2, REAL r );
# mode returned by the circles procedure                             #
MODE POSSIBLECIRCLES = UNION( INFINITECIRCLES, TWOCIRCLES, CIRCLE, NOCIRCLES );

# returns the circles of radius r that can be drawn through          #
#         points p1 and p2                                           #
PROC circles = ( POINT p1, POINT p2, REAL r )POSSIBLECIRCLES:
     IF r < 0 THEN # negative radius - there are no circles          #
         NOCIRCLES( "negative radius", p1, p2, r )
     ELIF p1 = p2 THEN # coincident points                           #
         IF r = 0.0 THEN
             # only one circle of radius 0 is possible               #
             CIRCLE( p1, 0.0 )
         ELSE
             # an infinite number of circles can be drawn through    #
             # the point                                             #
             INFINITECIRCLES( "infinite", r )
         FI
     ELSE # two possible circles                                     #
         REAL distance = p1 - p2;
         IF   distance > 2 * r THEN
             # the points are too far apart                          #
             NOCIRCLES( "points too far apart", p1, p2, r )
         ELIF distance = 2 * r THEN
             # the points are on the diameter of the circle          #
             CIRCLE( POINT( x OF p1 + ( ( p2 XDIFF p1 ) / 2 )
                          , y OF p1 + ( ( p2 YDIFF p1 ) / 2 )
                          )
                   , r
                   )
         ELSE
             # it is possible to draw two circles through the points #
             REAL half x sum      = ( x OF p1 + x OF p2 ) / 2;
             REAL half y sum      = ( y OF p1 + y OF p2 ) / 2;
             REAL mirror distance = sqrt( ( r * r ) - ( ( distance * distance ) / 4 ) );
             REAL x mirror        = ( mirror distance * ( y OF p1 - y OF p2 ) ) / distance;
             REAL y mirror        = ( mirror distance * ( x OF p2 - x OF p1 ) ) / distance;
             TWOCIRCLES( CIRCLE( POINT( half x sum + y mirror, half y sum + x mirror ), r )
                       , CIRCLE( POINT( half x sum - y mirror, half y sum - x mirror ), r )
                       )
         FI
     FI; # circles #

# test the circles procedure with the examples from the task    #

PROC print circles = ( REAL x1, y1, x2, y2, r )VOID:
     BEGIN
        CASE circles( POINT( x1, y1 ), POINT( x2, y2 ), r )
          IN ( NOCIRCLES       n ): print( ( "No circles : ", reason OF n ) )
           , ( TWOCIRCLES      t ): print( ( "Two circles: "
                                           , TOSTRING a OF t
                                           , ", "
                                           , TOSTRING b OF t
                                           )
                                         )
           , ( CIRCLE          c ): print( ( "One circle : ", TOSTRING c ) )
           , ( INFINITECIRCLES i ): print( ( "Infinite circles" ) )
         OUT BEGIN
                 print( ( "Unexpected circles result", newline ) );
                 stop
             END
        ESAC;
        print( ( newline ) )
     END; # print circles #
print circles( 0.1234, 0.9876,    0.8765, 0.2345,    2.0 );
print circles( 0.0000, 2.0000,    0.0000, 0.0000,    1.0 );
print circles( 0.1234, 0.9876,    0.1234, 0.9876,    2.0 );
print circles( 0.1234, 0.9876,    0.8765, 0.2345,    0.5 );
print circles( 0.1234, 0.9876,    0.1234, 0.9876,    0.0 )


CircleCenter(x1, y1, x2, y2, r){
	d := sqrt((x2-x1)**2 + (y2-y1)**2)
	x3 := (x1+x2)/2	, y3 := (y1+y2)/2
	cx1 := x3 + sqrt(r**2-(d/2)**2)*(y1-y2)/d , 	cy1:= y3 + sqrt(r**2-(d/2)**2)*(x2-x1)/d
	cx2 := x3 - sqrt(r**2-(d/2)**2)*(y1-y2)/d , 	cy2:= y3 - sqrt(r**2-(d/2)**2)*(x2-x1)/d
	if (d = 0)
		return "No circles can be drawn, points are identical"
	if (d = r*2)
		return "points are opposite ends of a diameter center = " cx1 "," cy1
	if (d = r*2)
		return "points are too far"
	if (r <= 0)
		return "radius is not valid"
	if !(cx1 && cy1 && cx2 && cy2)
		return "no solution"
	return cx1 "," cy1 " & " cx2 "," cy2
}


function twoCircles(x1, y1, x2, y2, radio)
	if x1 = x2 and y1 = y2 then  #Si los puntos coinciden
		if radio = 0 then        #a no ser que radio=0
			print "Los puntos son los mismos "
			return ""
		else
			print "Hay cualquier número de círculos a través de un solo punto ("; x1; ", "; y1; ") de radio "; int(radio)
			return ""
		end if
	end if
	r2 = sqr((x1-x2)^2+(y1-y2)^2) / 2  #distancia media entre puntos
	if radio < r2 then
		print "Los puntos están demasiado separados ("; 2*r2; ") - no hay círculos de radio "; int(radio)
		return ""
	end if

	#si no, calcular dos centros
	cx = (x1+x2) / 2   #punto medio
	cy = (y1+y2) / 2
	#debe moverse desde el punto medio a lo largo de la perpendicular en dd2
	dd2 = sqr(radio^2 - r2^2)   #distancia perpendicular
	dx1 = x2-cx           #vector al punto medio
	dy1 = y2-cy
	dx = 0-dy1 / r2*dd2   #perpendicular:
	dy = dx1 / r2*dd2     #rotar y escalar
	print " -> Circulo 1 ("; cx+dy; ", "; cy+dx; ")"     #dos puntos, con (+)
	print " -> Circulo 2 ("; cx-dy; ", "; cy-dx; ")"     #y (-)
	return ""
end function

#           p1                          p2            radio
x1 = 0.1234 : y1 = 0.9876 : x2 = 0.8765 : y2 = 0.2345 : radio = 2.0
print "Puntos "; "("; x1; ","; y1; "), ("; x2; ","; y2; ")"; ", Radio "; int(radio)
print twoCircles (x1, y1, x2, y2, radio)
x1 = 0.0000 : y1 = 2.0000 : x2 = 0.0000 : y2 = 0.0000 : radio = 1.0
print "Puntos "; "("; x1; ","; y1; "), ("; x2; ","; y2; ")"; ", Radio "; int(radio)
print twoCircles (x1, y1, x2, y2, radio)
x1 = 0.1234 : y1 = 0.9876 : x2 = 0.12345 : y2 = 0.9876 : radio = 2.0
print "Puntos "; "("; x1; ","; y1; "), ("; x2; ","; y2; ")"; ", Radio "; int(radio)
print twoCircles (x1, y1, x2, y2, radio)
x1 = 0.1234 : y1 = 0.9876 : x2 = 0.8765 : y2 = 0.2345 : radio = 0.5
print "Puntos "; "("; x1; ","; y1; "), ("; x2; ","; y2; ")"; ", Radio "; int(radio)
print twoCircles (x1, y1, x2, y2, radio)
x1 = 0.1234 : y1 = 0.9876 : x2 = 1234 : y2 = 0.9876 : radio = 0.0
print "Puntos "; "("; x1; ","; y1; "), ("; x2; ","; y2; ")"; ", Radio "; int(radio)
print twoCircles (x1, y1, x2, y2, radio)
end


#include<stdio.h>
#include<math.h>

typedef struct{
	double x,y;
	}point;

double distance(point p1,point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

void findCircles(point p1,point p2,double radius)
{
	double separation = distance(p1,p2),mirrorDistance;

	if(separation == 0.0)
	{
		radius == 0.0 ? printf("\nNo circles can be drawn through (%.4f,%.4f)",p1.x,p1.y):
							 printf("\nInfinitely many circles can be drawn through (%.4f,%.4f)",p1.x,p1.y);
	}

	else if(separation == 2*radius)
	{
		printf("\nGiven points are opposite ends of a diameter of the circle with center (%.4f,%.4f) and radius %.4f",(p1.x+p2.x)/2,(p1.y+p2.y)/2,radius);
	}

	else if(separation > 2*radius)
	{
		printf("\nGiven points are farther away from each other than a diameter of a circle with radius %.4f",radius);
	}

	else
	{
		mirrorDistance =sqrt(pow(radius,2) - pow(separation/2,2));

		printf("\nTwo circles are possible.");
		printf("\nCircle C1 with center (%.4f,%.4f), radius %.4f and Circle C2 with center (%.4f,%.4f), radius %.4f",(p1.x+p2.x)/2 + mirrorDistance*(p1.y-p2.y)/separation,(p1.y+p2.y)/2 + mirrorDistance*(p2.x-p1.x)/separation,radius,(p1.x+p2.x)/2 - mirrorDistance*(p1.y-p2.y)/separation,(p1.y+p2.y)/2 - mirrorDistance*(p2.x-p1.x)/separation,radius);
	}
}

int main()
{
    int i;

    point cases[] =
    {	{0.1234, 0.9876},    {0.8765, 0.2345},
	{0.0000, 2.0000},    {0.0000, 0.0000},
	{0.1234, 0.9876},    {0.1234, 0.9876},
	{0.1234, 0.9876},    {0.8765, 0.2345},
	{0.1234, 0.9876},    {0.1234, 0.9876}
    };

    double radii[] = {2.0,1.0,2.0,0.5,0.0};

    for(i=0;i<5;i++)
    {
	printf("\nCase %d)",i+1);
	findCircles(cases[2*i],cases[2*i+1],radii[i]);
    }

    return 0;
}


using System;
public class CirclesOfGivenRadiusThroughTwoPoints
{
    public static void Main()
    {
        double[][] values = new double[][] {
            new [] { 0.1234, 0.9876, 0.8765, 0.2345,   2 },
            new [] { 0.0,       2.0,    0.0,    0.0,   1 },
            new [] { 0.1234, 0.9876, 0.1234, 0.9876,   2 },
            new [] { 0.1234, 0.9876, 0.8765, 0.2345, 0.5 },
            new [] { 0.1234, 0.9876, 0.1234, 0.9876,   0 }
        };

        foreach (var a in values) {
            var p = new Point(a[0], a[1]);
            var q = new Point(a[2], a[3]);
            Console.WriteLine($"Points {p} and {q} with radius {a[4]}:");
            try {
                var centers = FindCircles(p, q, a[4]);
                Console.WriteLine("\t" + string.Join(" and ", centers));
            } catch (Exception ex) {
                Console.WriteLine("\t" + ex.Message);
            }
        }
    }

    static Point[] FindCircles(Point p, Point q, double radius) {
        if(radius < 0) throw new ArgumentException("Negative radius.");
        if(radius == 0) {
            if(p == q) return new [] { p };
            else throw new InvalidOperationException("No circles.");
        }
        if (p == q) throw new InvalidOperationException("Infinite number of circles.");

        double sqDistance = Point.SquaredDistance(p, q);
        double sqDiameter = 4 * radius * radius;
        if (sqDistance > sqDiameter) throw new InvalidOperationException("Points are too far apart.");

        Point midPoint = new Point((p.X + q.X) / 2, (p.Y + q.Y) / 2);
        if (sqDistance == sqDiameter) return new [] { midPoint };

        double d = Math.Sqrt(radius * radius - sqDistance / 4);
        double distance = Math.Sqrt(sqDistance);
        double ox = d * (q.X - p.X) / distance, oy = d * (q.Y - p.Y) / distance;
        return new [] {
            new Point(midPoint.X - oy, midPoint.Y + ox),
            new Point(midPoint.X + oy, midPoint.Y - ox)
        };
    }

    public struct Point
    {
        public Point(double x, double y) : this() {
            X = x;
            Y = y;
        }

        public double X { get; }
        public double Y { get; }

        public static bool operator ==(Point p, Point q) => p.X == q.X && p.Y == q.Y;
        public static bool operator !=(Point p, Point q) => p.X != q.X || p.Y != q.Y;

        public static double SquaredDistance(Point p, Point q) {
            double dx = q.X - p.X, dy = q.Y - p.Y;
            return dx * dx + dy * dy;
        }

        public override string ToString() => $"({X}, {Y})";

    }
}


#include <iostream>
#include <cmath>
#include <tuple>

struct point { double x, y; };

bool operator==(const point& lhs, const point& rhs)
{ return std::tie(lhs.x, lhs.y) == std::tie(rhs.x, rhs.y); }

enum result_category { NONE, ONE_COINCEDENT, ONE_DIAMETER, TWO, INFINITE };

using result_t = std::tuple<result_category, point, point>;

double distance(point l, point r)
{ return std::hypot(l.x - r.x, l.y - r.y); }

result_t find_circles(point p1, point p2, double r)
{
    point ans1 { 1/0., 1/0.}, ans2 { 1/0., 1/0.};
    if (p1 == p2) {
        if(r == 0.) return std::make_tuple(ONE_COINCEDENT, p1,   p2  );
        else        return std::make_tuple(INFINITE,       ans1, ans2);
    }
    point center { p1.x/2 + p2.x/2, p1.y/2 + p2.y/2};
    double half_distance = distance(center, p1);
    if(half_distance > r)      return std::make_tuple(NONE,         ans1,   ans2);
    if(half_distance - r == 0) return std::make_tuple(ONE_DIAMETER, center, ans2);
    double root = std::hypot(r, half_distance) / distance(p1, p2);
    ans1.x = center.x + root * (p1.y - p2.y);
    ans1.y = center.y + root * (p2.x - p1.x);
    ans2.x = center.x - root * (p1.y - p2.y);
    ans2.y = center.y - root * (p2.x - p1.x);
    return std::make_tuple(TWO, ans1, ans2);
}

void print(result_t result, std::ostream& out = std::cout)
{
    point r1, r2; result_category res;
    std::tie(res, r1, r2) = result;
    switch(res) {
      case NONE:
        out << "There are no solutions, points are too far away\n"; break;
      case ONE_COINCEDENT: case ONE_DIAMETER:
        out << "Only one solution: " << r1.x << ' ' << r1.y << '\n'; break;
      case INFINITE:
        out << "Infinitely many circles can be drawn\n"; break;
      case TWO:
        out << "Two solutions: " << r1.x << ' ' << r1.y << " and " << r2.x << ' ' << r2.y << '\n'; break;
    }
}

int main()
{
    constexpr int size = 5;
    const point points[size*2] = {
        {0.1234, 0.9876}, {0.8765, 0.2345}, {0.0000, 2.0000}, {0.0000, 0.0000},
        {0.1234, 0.9876}, {0.1234, 0.9876}, {0.1234, 0.9876}, {0.8765, 0.2345},
        {0.1234, 0.9876}, {0.1234, 0.9876}
    };
    const double radius[size] = {2., 1., 2., .5, 0.};

    for(int i = 0; i < size; ++i)
        print(find_circles(points[i*2], points[i*2 + 1], radius[i]));
}


import std.stdio, std.typecons, std.math;

class ValueException : Exception {
    this(string msg_) pure { super(msg_); }
}

struct V2 { double x, y; }
struct Circle { double x, y, r; }

/**Following explanation at:
http://mathforum.org/library/drmath/view/53027.html
*/
Tuple!(Circle, Circle)
circlesFromTwoPointsAndRadius(in V2 p1, in V2 p2, in double r)
pure in {
    assert(r >= 0, "radius can't be negative");
} body {
    enum nBits = 40;

    if (r.abs < (1.0 / (2.0 ^^ nBits)))
        throw new ValueException("radius of zero");

    if (feqrel(p1.x, p2.x) >= nBits &&
        feqrel(p1.y, p2.y) >= nBits)
        throw new ValueException("coincident points give" ~
                                 " infinite number of Circles");

    // Delta between points.
    immutable d = V2(p2.x - p1.x, p2.y - p1.y);

    // Distance between points.
    immutable q = sqrt(d.x ^^ 2 + d.y ^^ 2);
    if (q > 2.0 * r)
        throw new ValueException("separation of points > diameter");

    // Halfway point.
    immutable h = V2((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);

    // Distance along the mirror line.
    immutable dm = sqrt(r ^^ 2 - (q / 2) ^^ 2);

    return typeof(return)(
        Circle(h.x - dm * d.y / q, h.y + dm * d.x / q, r.abs),
        Circle(h.x + dm * d.y / q, h.y - dm * d.x / q, r.abs));
}

void main() {
    foreach (immutable t; [
                 tuple(V2(0.1234, 0.9876), V2(0.8765, 0.2345), 2.0),
                 tuple(V2(0.0000, 2.0000), V2(0.0000, 0.0000), 1.0),
                 tuple(V2(0.1234, 0.9876), V2(0.1234, 0.9876), 2.0),
                 tuple(V2(0.1234, 0.9876), V2(0.8765, 0.2345), 0.5),
                 tuple(V2(0.1234, 0.9876), V2(0.1234, 0.9876), 0.0)]) {
        writefln("Through points:\n  %s   %s  and radius %f\n" ~
                 "You can construct the following circles:", t[]);
        try {
            writefln("  %s\n  %s\n",
                     circlesFromTwoPointsAndRadius(t[])[]);
        } catch (ValueException v)
            writefln("  ERROR: %s\n", v.msg);
    }
}


program Circles_of_given_radius_through_two_points;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Types,
  System.Math;

const
  Cases: array[0..9] of TPointF = ((
    x: 0.1234;
    y: 0.9876
  ), (
    x: 0.8765;
    y: 0.2345
  ), (
    x: 0.0000;
    y: 2.0000
  ), (
    x: 0.0000;
    y: 0.0000
  ), (
    x: 0.1234;
    y: 0.9876
  ), (
    x: 0.1234;
    y: 0.9876
  ), (
    x: 0.1234;
    y: 0.9876
  ), (
    x: 0.8765;
    y: 0.2345
  ), (
    x: 0.1234;
    y: 0.9876
  ), (
    x: 0.1234;
    y: 0.9876
  ));
  radii: array of double = [2.0, 1.0, 2.0, 0.5, 0.0];

procedure FindCircles(p1, p2: TPointF; radius: double);
var
  separation, mirrorDistance: double;
begin
  separation := p1.Distance(p2);
  if separation = 0.0 then
  begin
    if radius = 0 then
      write(format(#10'No circles can be drawn through (%.4f,%.4f)', [p1.x, p1.y]))
    else
      write(format(#10'Infinitely many circles can be drawn through (%.4f,%.4f)',
        [p1.x, p1.y]));
    exit;
  end;

  if separation = 2 * radius then
  begin
    write(format(#10'Given points are opposite ends of a diameter of the circle with center (%.4f,%.4f) and radius %.4f',
      [(p1.x + p2.x) / 2, (p1.y + p2.y) / 2, radius]));
    exit;
  end;

  if separation > 2 * radius then
  begin
    write(format(#10'Given points are farther away from each other than a diameter of a circle with radius %.4f',
      [radius]));
    exit;
  end;

  mirrorDistance := sqrt(Power(radius, 2) - Power(separation / 2, 2));
  write(#10'Two circles are possible.');
  write(format(#10'Circle C1 with center (%.4f,%.4f), radius %.4f and Circle C2 with center (%.4f,%.4f), radius %.4f',
    [(p1.x + p2.x) / 2 + mirrorDistance * (p1.y - p2.y) / separation, (p1.y + p2.y)
    / 2 + mirrorDistance * (p2.x - p1.x) / separation, radius, (p1.x + p2.x) / 2
    - mirrorDistance * (p1.y - p2.y) / separation, (p1.y + p2.y) / 2 -
    mirrorDistance * (p2.x - p1.x) / separation, radius]));

end;

begin
  for var i := 0 to 4 do
  begin
    write(#10'Case ', i + 1,')');
    findCircles(cases[2 * i], cases[2 * i + 1], radii[i]);
  end;
  readln;
end.


defmodule RC do
  def circle(p, p, r) when r>0.0 do
    raise ArgumentError, message: "Infinite number of circles, points coincide."
  end
  def circle(p, p, r) when r==0.0 do
    {px, py} = p
    [{px, py, r}]
  end
  def circle({p1x,p1y}, {p2x,p2y}, r) do
    {dx, dy} = {p2x-p1x, p2y-p1y}
    q = :math.sqrt(dx*dx + dy*dy)
    if q > 2*r do
      raise ArgumentError, message: "Distance of points > diameter."
    else
      {x3, y3} = {(p1x+p2x) / 2, (p1y+p2y) / 2}
      d = :math.sqrt(r*r - q*q/4)
      Enum.uniq([{x3 - d*dy/q, y3 + d+dx/q, r}, {x3 + d*dy/q, y3 - d*dx/q, r}])
    end
  end
end

data = [{{0.1234, 0.9876}, {0.8765, 0.2345}, 2.0},
        {{0.0000, 2.0000}, {0.0000, 0.0000}, 1.0},
        {{0.1234, 0.9876}, {0.1234, 0.9876}, 2.0},
        {{0.1234, 0.9876}, {0.8765, 0.2345}, 0.5},
        {{0.1234, 0.9876}, {0.1234, 0.9876}, 0.0}]

Enum.each(data, fn {p1, p2, r} ->
  IO.write "Given points:\n  #{inspect p1},\n  #{inspect p2}\n  and radius #{r}\n"
  try do
    circles = RC.circle(p1, p2, r)
    IO.puts "You can construct the following circles:"
    Enum.each(circles, fn circle -> IO.puts "  #{inspect circle}" end)
  rescue
    e in ArgumentError -> IO.inspect e
  end
  IO.puts ""
end)


PROGRAM CIRCLES

!
! for rosettacode.org
!

PROCEDURE CIRCLE_CENTER(X1,Y1,X2,Y2,R->MSG$)
  LOCAL D,W,X3,Y3

        D=SQR((X2-X1)^2+(Y2-Y1)^2)
        IF D=0 THEN
             MSG$="NO CIRCLES CAN BE DRAWN, POINTS ARE IDENTICAL"
             EXIT PROCEDURE
        END IF
        X3=(X1+X2)/2  Y3=(Y1+Y2)/2

        W=R^2-(D/2)^2
        IF W<0 THEN
             MSG$="NO SOLUTION"
             EXIT PROCEDURE
        END IF
        CX1=X3+SQR(W)*(Y1-Y2)/D   CY1=Y3+SQR(W)*(X2-X1)/D
        CX2=X3-SQR(W)*(Y1-Y2)/D   CY2=Y3-SQR(W)*(X2-X1)/D
        IF D=R*2 THEN
             MSG$="POINTS ARE OPPOSITE ENDS OF A DIAMETER CENTER = "+STR$(CX1)+","+STR$(CY1)
             EXIT PROCEDURE
        END IF
        IF D>R*2 THEN
             MSG$="POINTS ARE TOO FAR"
             EXIT PROCEDURE
        END IF
        IF R<=0 THEN
             MSG$="RADIUS IS NOT VALID"
             EXIT PROCEDURE
        END IF
        MSG$=STR$(CX1)+","+STR$(CY1)+" & "+STR$(CX2)+","+STR$(CY2)
END PROCEDURE

BEGIN
DATA(0.1234,0.9876,0.8765,0.2345,2.0)
DATA(0.0000,2.0000,0.0000,0.0000,1.0)
DATA(0.1234,0.9876,0.1234,0.9876,2.0)
DATA(0.1234,0.9876,0.8765,0.2345,0.5)
DATA(0.1234,0.9876,0.1234,0.9876,0.0)

FOR I%=1 TO 5 DO
   READ(PX,PY,QX,QY,RADIUS)
   CIRCLE_CENTER(PX,PY,QX,QY,RADIUS->MSG$)
   PRINT(MSG$)
END FOR
END PROGRAM


open System

let add (a:double, b:double) (x:double, y:double) = (a + x, b + y)
let sub (a:double, b:double) (x:double, y:double) = (a - x, b - y)
let magSqr (a:double, b:double) = a * a + b * b
let mag a:double = Math.Sqrt(magSqr a)
let mul (a:double, b:double) c = (a * c, b * c)
let div2 (a:double, b:double) c = (a / c, b / c)
let perp (a:double, b:double) = (-b, a)
let norm a = div2 a (mag a)

let circlePoints p q (radius:double) =
    let diameter = radius * 2.0
    let pq = sub p q
    let magPQ = mag pq
    let midpoint = div2 (add p q) 2.0
    let halfPQ = magPQ / 2.0
    let magMidC = Math.Sqrt(Math.Abs(radius * radius - halfPQ * halfPQ))
    let midC = mul (norm (perp pq)) magMidC
    let center1 = add midpoint midC
    let center2 = sub midpoint midC
    if radius = 0.0 then None
    else if p = q then None
    else if diameter < magPQ then None
    else Some (center1, center2)

[<EntryPoint>]
let main _ =
    printfn "%A" (circlePoints (0.1234, 0.9876) (0.8765, 0.2345) 2.0)
    printfn "%A" (circlePoints (0.0, 2.0) (0.0, 0.0) 1.0)
    printfn "%A" (circlePoints (0.1234, 0.9876) (0.1234, 0.9876) 2.0)
    printfn "%A" (circlePoints (0.1234, 0.9876) (0.8765, 0.2345) 0.5)
    printfn "%A" (circlePoints (0.1234, 0.9876) (0.1234, 0.1234) 0.0)

    0 // return an integer exit code


USING: accessors combinators combinators.short-circuit
formatting io kernel literals locals math math.distances
math.functions prettyprint sequences strings ;
IN: rosetta-code.circles
DEFER: find-circles

! === Input ====================================================

TUPLE: input p1 p2 r ;

CONSTANT: test-cases {
    T{ input f { 0.1234 0.9876 } { 0.8765 0.2345 } 2 }
    T{ input f { 0 2 } { 0 0 } 1 }
    T{ input f { 0.1234 0.9876 } { 0.1234 0.9876 } 2 }
    T{ input f { 0.1234 0.9876 } { 0.8765 0.2345 } 0.5 }
    T{ input f { 0.1234 0.9876 } { 0.1234 0.9876 } 0 }
}

! === Edge case handling =======================================

CONSTANT: infinite
    "there could be an infinite number of circles."

CONSTANT: too-far
    "points are too far apart to form circles."

: coincident? ( input -- ? ) [ p1>> ] [ p2>> ] bi = ;

: degenerate? ( input -- ? )
    { [ r>> zero? ] [ coincident? ] } 1&& ;

: infinite? ( input -- ? )
    { [ r>> zero? not ] [ coincident? ] } 1&& ;

: too-far? ( input -- ? )
    [ r>> 2 * ] [ p1>> ] [ p2>> ] tri euclidian-distance < ;

: degenerate ( input -- str )
    p1>> [ first ] [ second ] bi
    "one degenerate circle found at (%.4f, %.4f).\n" sprintf ;

: check-input ( input -- obj )
    {
        { [ dup infinite?   ] [ drop infinite ] }
        { [ dup too-far?    ] [ drop too-far  ] }
        { [ dup degenerate? ] [ degenerate    ] }
        [ find-circles ]
    } cond ;

! === Program Logic ============================================

:: (circle-coords) ( a b c r q quot -- x )
    a r sq q 2 / sq - sqrt b c - * q / quot call ; inline

: circle-coords ( quot -- x y )
    [ + ] over [ - ] [ [ call ] dip (circle-coords) ] [email protected] ;
    inline

:: find-circles ( input -- circles )
    input [ r>> ] [ p1>> ] [ p2>> ] tri    :> ( r p1 p2 )
    p1 p2 [ [ first ] [ second ] bi ] [email protected]  :> ( x1 y1 x2 y2 )
    x1 x2 y1 y2 [ + 2 / ] [email protected]             :> ( x3 y3 )
    p1 p2 euclidian-distance               :> q
    [ x3 y1 y2 r q ]
    [ y3 x2 x1 r q ] [ circle-coords ] [email protected] :> ( x w y z )
    { x y } { w z } = { { x y } } { { w z } { x y } } ? ;

! === Output ===================================================

: .point ( seq -- )
    [ first ] [ second ] bi "(%.4f, %.4f)" printf ;

: .given ( input -- )
    [ r>> ] [ p2>> ] [ p1>> ] tri
    "Given points " write .point ", " write .point
    ", and radius %.2f,\n" printf ;

: .one ( seq -- )
    first "one circle found at " write .point "." print ;

: .two ( seq -- )
    [ first ] [ second ] bi "two circles found at " write
    .point " and " write .point "." print ;

: .circles ( seq -- ) dup length 1 = [ .one ] [ .two ] if ;

! === Main word ================================================

: circles-demo ( -- )
    test-cases [
        dup .given check-input dup string?
        [ print ] [ .circles ] if nl
    ] each ;

MAIN: circles-demo


! Implemented by Anant Dixit (Nov. 2014)
! Transpose elements in find_center to obtain correct results. R.N. McLean (Dec 2017)
program circles
implicit none
double precision :: P1(2), P2(2), R

P1 = (/0.1234d0, 0.9876d0/)
P2 = (/0.8765d0,0.2345d0/)
R = 2.0d0
call print_centers(P1,P2,R)

P1 = (/0.0d0, 2.0d0/)
P2 = (/0.0d0,0.0d0/)
R = 1.0d0
call print_centers(P1,P2,R)

P1 = (/0.1234d0, 0.9876d0/)
P2 = (/0.1234d0, 0.9876d0/)
R = 2.0d0
call print_centers(P1,P2,R)

P1 = (/0.1234d0, 0.9876d0/)
P2 = (/0.8765d0, 0.2345d0/)
R = 0.5d0
call print_centers(P1,P2,R)

P1 = (/0.1234d0, 0.9876d0/)
P2 = (/0.1234d0, 0.9876d0/)
R = 0.0d0
call print_centers(P1,P2,R)
end program circles

subroutine print_centers(P1,P2,R)
implicit none
double precision :: P1(2), P2(2), R, Center(2,2)
integer :: Res
call test_inputs(P1,P2,R,Res)
write(*,*)
write(*,'(A10,F7.4,A1,F7.4)') 'Point1  : ', P1(1), ' ', P1(2)
write(*,'(A10,F7.4,A1,F7.4)') 'Point2  : ', P2(1), ' ', P2(2)
write(*,'(A10,F7.4)') 'Radius  : ', R
if(Res.eq.1) then
  write(*,*) 'Same point because P1=P2 and r=0.'
elseif(Res.eq.2) then
  write(*,*) 'No circles can be drawn because r=0.'
elseif(Res.eq.3) then
  write(*,*) 'Infinite circles because P1=P2 for non-zero radius.'
elseif(Res.eq.4) then
  write(*,*) 'No circles with given r can be drawn because points are far apart.'
elseif(Res.eq.0) then
  call find_center(P1,P2,R,Center)
  if(Center(1,1).eq.Center(2,1) .and. Center(1,2).eq.Center(2,2)) then
    write(*,*) 'Points lie on the diameter. A single circle can be drawn.'
    write(*,'(A10,F7.4,A1,F7.4)') 'Center  : ', Center(1,1), ' ', Center(1,2)
  else
    write(*,*) 'Two distinct circles found.'
    write(*,'(A10,F7.4,A1,F7.4)') 'Center1 : ', Center(1,1), ' ', Center(1,2)
    write(*,'(A10,F7.4,A1,F7.4)') 'Center2 : ', Center(2,1), ' ', Center(2,2)
  end if
elseif(Res.lt.0) then
  write(*,*) 'Incorrect value for r.'
end if
write(*,*)
end subroutine print_centers

subroutine test_inputs(P1,P2,R,Res)
implicit none
double precision :: P1(2), P2(2), R, dist
integer :: Res
if(R.lt.0.0d0) then
  Res = -1
  return
elseif(R.eq.0.0d0 .and. P1(1).eq.P2(1) .and. P1(2).eq.P2(2)) then
  Res = 1
  return
elseif(R.eq.0.0d0) then
  Res = 2
  return
elseif(P1(1).eq.P2(1) .and. P1(2).eq.P2(2)) then
  Res = 3
  return
else
  dist = sqrt( (P1(1)-P2(1))**2 + (P1(2)-P2(2))**2 )
  if(dist.gt.2.0d0*R) then
    Res = 4
    return
  else
    Res = 0
    return
  end if
end if
end subroutine test_inputs

subroutine find_center(P1,P2,R,Center)
implicit none
double precision :: P1(2), P2(2), MP(2), Center(2,2), R, dm, dd
MP = (P1 + P2)/2.0d0
dm = sqrt((P1(1) - P2(1))**2 + (P1(2) - P2(2))**2)
dd = sqrt(R**2 - (dm/2.0d0)**2)
Center(1,1) = MP(1) - dd*(P2(2) - P1(2))/dm
Center(1,2) = MP(2) + dd*(P2(1) - P1(1))/dm

Center(2,1) = MP(1) + dd*(P2(2) - P1(2))/dm
Center(2,2) = MP(2) - dd*(P2(1) - P1(1))/dm
end subroutine find_center


Type Point
    As Double x,y
    Declare Property length As Double
End Type

Property point.length As Double
Return Sqr(x*x+y*y)
End Property

Sub circles(p1 As Point,p2 As Point,radius As Double)
    Print "Points ";"("&p1.x;","&p1.y;"),("&p2.x;","&p2.y;")";", Rad ";radius
    Var ctr=Type<Point>((p1.x+p2.x)/2,(p1.y+p2.y)/2)
    Var half=Type<Point>(p1.x-ctr.x,p1.y-ctr.y)
    Var lenhalf=half.length
    If radius<lenhalf Then Print "Can't solve":Print:Exit Sub
    If lenhalf=0 Then Print "Points are the same":Print:Exit Sub
    Var dist=Sqr(radius^2-lenhalf^2)/lenhalf
    Var rot= Type<Point>(-dist*(p1.y-ctr.y) +ctr.x,dist*(p1.x-ctr.x) +ctr.y)
    Print " -> Circle 1 ("&rot.x;","&rot.y;")"
    rot= Type<Point>(-(rot.x-ctr.x) +ctr.x,-((rot.y-ctr.y)) +ctr.y)
    Print" -> Circle 2 ("&rot.x;","&rot.y;")"
    Print
End Sub

Dim As Point p1=(.1234,.9876),p2=(.8765,.2345)
circles(p1,p2,2)
p1=Type<Point>(0,2):p2=Type<Point>(0,0)
circles(p1,p2,1)
p1=Type<Point>(.1234,.9876):p2=p1
circles(p1,p2,2)
p1=Type<Point>(.1234,.9876):p2=Type<Point>(.8765,.2345)
circles(p1,p2,.5)
p1=Type<Point>(.1234,.9876):p2=p1
circles(p1,p2,0)

Sleep


package main

import (
    "fmt"
    "math"
)

var (
    Two  = "Two circles."
    R0   = "R==0.0 does not describe circles."
    Co   = "Coincident points describe an infinite number of circles."
    CoR0 = "Coincident points with r==0.0 describe a degenerate circle."
    Diam = "Points form a diameter and describe only a single circle."
    Far  = "Points too far apart to form circles."
)

type point struct{ x, y float64 }

func circles(p1, p2 point, r float64) (c1, c2 point, Case string) {
    if p1 == p2 {
        if r == 0 {
            return p1, p1, CoR0
        }
        Case = Co
        return
    }
    if r == 0 {
        return p1, p2, R0
    }
    dx := p2.x - p1.x
    dy := p2.y - p1.y
    q := math.Hypot(dx, dy)
    if q > 2*r {
        Case = Far
        return
    }
    m := point{(p1.x + p2.x) / 2, (p1.y + p2.y) / 2}
    if q == 2*r {
        return m, m, Diam
    }
    d := math.Sqrt(r*r - q*q/4)
    ox := d * dx / q
    oy := d * dy / q
    return point{m.x - oy, m.y + ox}, point{m.x + oy, m.y - ox}, Two
}

var td = []struct {
    p1, p2 point
    r      float64
}{
    {point{0.1234, 0.9876}, point{0.8765, 0.2345}, 2.0},
    {point{0.0000, 2.0000}, point{0.0000, 0.0000}, 1.0},
    {point{0.1234, 0.9876}, point{0.1234, 0.9876}, 2.0},
    {point{0.1234, 0.9876}, point{0.8765, 0.2345}, 0.5},
    {point{0.1234, 0.9876}, point{0.1234, 0.9876}, 0.0},
}

func main() {
    for _, tc := range td {
        fmt.Println("p1: ", tc.p1)
        fmt.Println("p2: ", tc.p2)
        fmt.Println("r: ", tc.r)
        c1, c2, Case := circles(tc.p1, tc.p2, tc.r)
        fmt.Println("  ", Case)
        switch Case {
        case CoR0, Diam:
            fmt.Println("   Center: ", c1)
        case Two:
            fmt.Println("   Center 1: ", c1)
            fmt.Println("   Center 2: ", c2)
        }
        fmt.Println()
    }
}


class Circles {
    private static class Point {
        private final double x, y

        Point(Double x, Double y) {
            this.x = x
            this.y = y
        }

        double distanceFrom(Point other) {
            double dx = x - other.x
            double dy = y - other.y
            return Math.sqrt(dx * dx + dy * dy)
        }

        @Override
        boolean equals(Object other) {
            //if (this == other) return true
            if (other == null || getClass() != other.getClass()) return false
            Point point = (Point) other
            return x == point.x && y == point.y
        }

        @Override
        String toString() {
            return String.format("(%.4f, %.4f)", x, y)
        }
    }

    private static Point[] findCircles(Point p1, Point p2, double r) {
        if (r < 0.0) throw new IllegalArgumentException("the radius can't be negative")
        if (r == 0.0.toDouble() && p1 != p2) throw new IllegalArgumentException("no circles can ever be drawn")
        if (r == 0.0.toDouble()) return [p1, p1]
        if (Objects.equals(p1, p2)) throw new IllegalArgumentException("an infinite number of circles can be drawn")
        double distance = p1.distanceFrom(p2)
        double diameter = 2.0 * r
        if (distance > diameter) throw new IllegalArgumentException("the points are too far apart to draw a circle")
        Point center = new Point((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0)
        if (distance == diameter) return [center, center]
        double mirrorDistance = Math.sqrt(r * r - distance * distance / 4.0)
        double dx = (p2.x - p1.x) * mirrorDistance / distance
        double dy = (p2.y - p1.y) * mirrorDistance / distance
        return [
            new Point(center.x - dy, center.y + dx),
            new Point(center.x + dy, center.y - dx)
        ]
    }

    static void main(String[] args) {
        Point[] p = [
            new Point(0.1234, 0.9876),
            new Point(0.8765, 0.2345),
            new Point(0.0000, 2.0000),
            new Point(0.0000, 0.0000)
        ]
        Point[][] points = [
            [p[0], p[1]],
            [p[2], p[3]],
            [p[0], p[0]],
            [p[0], p[1]],
            [p[0], p[0]],
        ]
        double[] radii = [2.0, 1.0, 2.0, 0.5, 0.0]
        for (int i = 0; i < radii.length; ++i) {
            Point p1 = points[i][0]
            Point p2 = points[i][1]
            double r = radii[i]
            printf("For points %s and %s with radius %f\n", p1, p2, r)
            try {
                Point[] circles = findCircles(p1, p2, r)
                Point c1 = circles[0]
                Point c2 = circles[1]
                if (Objects.equals(c1, c2)) {
                    printf("there is just one circle with center at %s\n", c1)
                } else {
                    printf("there are two circles with centers at %s and %s\n", c1, c2)
                }
            } catch (IllegalArgumentException ex) {
                println(ex.getMessage())
            }
            println()
        }
    }
}


add (a, b) (x, y) = (a + x, b + y)
sub (a, b) (x, y) = (a - x, b - y)
magSqr (a, b)     = (a ^^ 2) + (b ^^ 2)
mag a             = sqrt $ magSqr a
mul (a, b) c      = (a * c, b * c)
div2 (a, b) c     = (a / c, b / c)
perp (a, b)       = (negate b, a)
norm a            = a `div2` mag a

circlePoints :: (Ord a, Floating a) =>
                (a, a) -> (a, a) -> a -> Maybe ((a, a), (a, a))
circlePoints p q radius
  | radius == 0      = Nothing
  | p == q           = Nothing
  | diameter < magPQ = Nothing
  | otherwise        = Just (center1, center2)
  where
    diameter = radius * 2
    pq       = p `sub` q
    magPQ    = mag pq
    midpoint = (p `add` q) `div2` 2
    halfPQ   = magPQ / 2
    magMidC  = sqrt . abs $ (radius ^^ 2) - (halfPQ ^^ 2)
    midC     = (norm $ perp pq) `mul` magMidC
    center1  = midpoint `add` midC
    center2  = midpoint `sub` midC

uncurry3 f (a, b, c) = f a b c

main :: IO ()
main = mapM_ (print . uncurry3 circlePoints)
  [((0.1234, 0.9876), (0.8765, 0.2345), 2),
   ((0     , 2     ), (0     , 0     ), 1),
   ((0.1234, 0.9876), (0.1234, 0.9876), 2),
   ((0.1234, 0.9876), (0.8765, 0.2345), 0.5),
   ((0.1234, 0.9876), (0.1234, 0.1234), 0)]


average =: +/ % #

circles =: verb define"1
 'P0 P1 R' =. (j./"1)_2[\y NB. Use complex plane
 C =. P0 [email protected]:, P1
 BAD =: ":@:+. C
 SEPARATION =. P0 |@- P1
 if. 0 = SEPARATION do.
  if. 0 = R do. 'Degenerate point at ' , BAD
  else. 'Any center at a distance ' , (":R) , ' from ' , BAD , ' works.'
  end.
 elseif. SEPARATION (> +:) R do. 'No solutions.'
 elseif. SEPARATION (= +:) R do. 'Duplicate solutions with center at ' , BAD
 elseif. 1 do.
  ORTHOGONAL_DISTANCE =. R * 1 o. _2 o. R %~ | C - P0
  UNIT =: P1 *@:- P0
  OFFSETS =: ORTHOGONAL_DISTANCE * UNIT * j. _1 1
  C [email protected]:+ OFFSETS
 end.
)

INPUT=: ".;._2]0 :0
 0.1234 0.9876 0.8765 0.2345   2
      0      2      0      0   1
 0.1234 0.9876 0.1234 0.9876   2
 0.1234 0.9876 0.8765 0.2345 0.5
 0.1234 0.9876 0.1234 0.9876   0
)

   ('x0 y0 x1 y1 r' ; 'center'),(;circles)"1 INPUT
┌───────────────────────────────┬────────────────────────────────────────────────────┐
│x0 y0 x1 y1 r                  │center                                              │
├───────────────────────────────┼────────────────────────────────────────────────────┤
│0.1234 0.9876 0.8765 0.2345 2  │_0.863212 _0.752112                                 │
│                               │  1.86311   1.97421                                 │
├───────────────────────────────┼────────────────────────────────────────────────────┤
│0 2 0 0 1                      │Duplicate solutions with center at 0 1              │
├───────────────────────────────┼────────────────────────────────────────────────────┤
│0.1234 0.9876 0.1234 0.9876 2  │Any center at a distance 2 from 0.1234 0.9876 works.│
├───────────────────────────────┼────────────────────────────────────────────────────┤
│0.1234 0.9876 0.8765 0.2345 0.5│No solutions.                                       │
├───────────────────────────────┼────────────────────────────────────────────────────┤
│0.1234 0.9876 0.1234 0.9876 0  │Degenerate point at 0.1234 0.9876                   │
└───────────────────────────────┴────────────────────────────────────────────────────┘