(defn distance [[x1 y1] [x2 y2]] (let [dx (- x2 x1), dy (- y2 y1)] (Math/sqrt (+ (* dx dx) (* dy dy))))) (defn brute-force [points] (let [n (count points)] (when (< 1 n) (apply min-key first (for [i (range 0 (dec n)), :let [p1 (nth points i)], j (range (inc i) n), :let [p2 (nth points j)]] [(distance p1 p2) p1 p2]))))) (defn combine [yS [dmin pmin1 pmin2]] (apply min-key first (conj (for [[p1 p2] (partition 2 1 yS) :let [[_ py1] p1 [_ py2] p2] :while (< (- py1 py2) dmin)] [(distance p1 p2) p1 p2]) [dmin pmin1 pmin2]))) (defn closest-pair ([points] (closest-pair (sort-by first points) (sort-by second points))) ([xP yP] (if (< (count xP) 4) (brute-force xP) (let [[xL xR] (partition-all (Math/ceil (/ (count xP) 2)) xP) [xm _] (last xL) {yL true yR false} (group-by (fn [[px _]] (<= px xm)) yP) dL&pairL (closest-pair xL yL) dR&pairR (closest-pair xR yR) [dmin pmin1 pmin2] (min-key first dL&pairL dR&pairR) {yS true} (group-by (fn [[px _]] (< (Math/abs (- xm px)) dmin)) yP)] (combine yS [dmin pmin1 pmin2])))))