Recursive euclidean distance

瘦欲@ 提交于 2019-11-29 18:16:11

The only time recursive algorithm for this would be sensible if the input are two vectors (represented by lists) of any dimension, not only 2 or 3. In this case this will compute the square of the distance:

(defun sq-euclid-distance (p q)
  (cond ((or (null p) (null q)) 0)
        (t (+ (expt (- (car p) (car q)) 2)
              (sq-euclid-distance (cdr p) (cdr q))))))

To get SQRT out of it you would need to make it into a auxiliary helper and make a driver computing the square root.

(defun euclid-distance (p q) (sqrt sq-euclid-distance p q))

PS. I am not checking if p and q are atoms, but they can be treated as 1-dimensional vectors. Returning NIL from the function that is expected to provide a numerical value is not a great idea.

Looking at this Haskell thread, I think your task is more likely to compute the distance of n-dimensional vectors, i.e. sqrt((x1-y1)^2 + ... + (xn-yn)^2).

In your example there is no iteration, you just access elements inside two lists. In other words: you assume that P and Q contains 2 elements and I think the question is to generalize this to N elements.

Moreover, you are doing many useless checks in order to return nil instead of letting errors be signaled. For example, if the lists do not contain numbers, you should probably not return nil.

I would rewrite your version like this:

(defun euclidean-distance-it (p q)
  (destructuring-bind (x1 x2) p
    (destructuring-bind (y1 y2) q
      (sqrt (+ (expt (- x1 y1) 2)
               (expt (- x2 y2) 2))))))

With a recursive version, I consider that p and q are two mathematical vectors, so that p contains different coordinates (p1, ..., pn), which differs from your implementation where p contains all x's and q all y's.

So, you have to compute (pi - qi)^2 for each for pair (pi, qi) of elements taken in parallel from p and q, sum the intermediate values and take the square root. With high-order functions, you don't even need to use recursion.

I won't spoil you the recursive answer, but here is a higher-order function version:

(defun distance (p q) 
  (sqrt
    (reduce #'+ 
      (map 'list
        (lambda (px qx) (expt (- px qx) 2)) 
        p q))))

And another one with loop:

(defun distance (p q)
  (sqrt (loop for px in p
              for qx in q
              sum (expt (- px qx) 2))))
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!