Search code examples
clojure

Extracting two map elements with the largest distance in Clojure


I am trying to extract two elements of a map with the largest distance. For that, I defined the function for calculating the distance and can obtain the distance between the first element (p1) and other elements of the map. But I need to calculate distances between the second item (p2) and the next ones (p3, p4, p5), the third item (p3) and (p4, p5), the fourth item (p4) and fifth item (p5). Then I need to identify the maximum amount between all distances and return the 2 items with the largest distance and the distance itself. Any help is highly appreciated. Here is my code:

(defn eclid-dist
  [u v]
  (Math/sqrt (apply + (map #(* % %) (mapv - u v)))))


(def error
  {:p1 [1 2 3]
   :p2 [4 5 6]
   :p3 [7 8 9]
   :p4 [1 2 3]
   :p5 [6 5 4]})


(dotimes [i (dec (count error))]
  (let [dis (eclid-dist (second (nth (seq error) 0))
                        (second (nth (seq error) (+ i 1))))
        max-error (max dis)]
    (println [':dis' dis ':max-error' max-error])))

I tried to save each calculated distance as a vector element separately to prevent overwriting but it was not successful.


Solution

  • You could use the for macro for this. It let's you combine two nested loops to test for all pairs. Then you can use max-key to pick the pair with largest distance:

    (defn find-largest-dist-pair [vec-map]
      (apply max-key second
             (for [[[k0 v0] & r] (iterate rest vec-map)
                   :while r
                   [k1 v1] r]
               [[k0 k1] (eclid-dist v0 v1)])))
    
    (find-largest-dist-pair error)
    ;; => [[:p3 :p4] 10.392304845413264]