Finding maximum distance between two points in a list (scheme)

前端 未结 3 1901
有刺的猬
有刺的猬 2021-01-28 09:49

I\'m currently trying to write a function from a list of points that returns the distance from a point p to a point in my point list that is farthest away from p. My list of poi

相关标签:
3条回答
  • 2021-01-28 10:22

    get-yshould use cdr, not car.

    get-x and get-y miss a closing parenthesis.

    For max-distance, I'd go for

    (define (max-distance p pt-list)
      (apply max (map (lambda (x) (distance p x)) pt-list)))
    

    which means that you don't need get-first-point and get-rest-points.

    Illustration (using (1 . 1) as p):

    > (map (lambda (x) (distance '(1 . 1) x)) '((2 . 4) (3 . 6) (5 . 12) (-4 . 3) (8.4 . 9) (0 . -1)))
    '(3.1622776601683795 5.385164807134504 11.704699910719626 5.385164807134504 10.897706180660222 2.23606797749979)
    
    > (apply max (map (lambda (x) (distance '(1 . 1) x)) '((2 . 4) (3 . 6) (5 . 12) (-4 . 3) (8.4 . 9) (0 . -1))))
    11.704699910719626
    

    Depending on your definition of "farthest" you may want to include abs in the expression.

    0 讨论(0)
  • 2021-01-28 10:33

    This is a case where you want to fold a function f over your list of points. The function f should take a distance d and point x and return the maximum d and the distance between x and your special designated point p. I've described folds in a bit more detail in some other answers:

    • Flattening a List of Lists
    • Another way of writing a mimum value procedure in Scheme?

    The main point is that in a fold, you take a function, an initial value, and a list. You apply the function to the first element of the list and the initial value to produce some new value. Now you recursively fold with the the same function, the new value, and the rest of the list. This is essentially a loop like this:

    current value = initial value
    while list is not empty
         current value = result of function called with first element of list and current value
         list = rest of list
    return current value

    In Scheme, where tail call optimization is guaranteed, it is that loop. In your case, you just need to determine what the initial value should be, and what the function should be. Since distances are always non-negative, a reasonable initial value is zero. The function is a bit more complicated. current value will be a distance, but the first element of list will be a point. The result of the function needs to be a new distance, and the new distance should be the maximum of the distance current value and the distance between some the point from list and the special point. In Racket, this kind of fold is called foldl, so we end up with something like this:

    (define special-points '((2 . 4) (3 . 6) (5 . 12) (-4 . 3) (8.4 . 9) (0 . -1)))
    
    (define (distance a b)
      (let ((square (lambda (x)
                      (* x x))))
        (sqrt (+ (square (- (car a) (car b)))
                 (square (- (cdr a) (cdr b)))))))
    
    (define (max-distance point points)
      (foldl (lambda (current-point current-distance)
               (max current-distance
                    (distance point current-point)))
             0
             points))
    
    > (max-distance '(4 . 12) special-points)
    13.601470508735444
    > (max-distance '(8 . 8) special-points)
    13.0
    > (max-distance '(2 . 5) special-points)
    7.615773105863909
    

    If you're not using Racket, you'll have to write your own foldl, but it's really not very hard. (This actually isn't quite as sophisticated as Racket's foldl, which can take any positive number of lists, but it will work for this case.)

    (define (foldl function initial-value list)
      (if (null? list)
          initial-value
          (foldl function
                 (function (car list) initial-value)
                 (cdr list))))
    
    0 讨论(0)
  • 2021-01-28 10:36

    Compute the distance to the car of points. Either that distance is the maximum or the maximum from the cdr of points is. Result is a simple recursive algorithm traversing the list of points.

    (define (max-distance-p p points)
      (if (null? points)
          0
          (max (distance p (car points))
               (max-distance-p p (cdr points)))))
    

    The 0 is returned if you pass in points as an empty list; that might be a bit questionable. If so:

    (define (max-distance-p p points)
      (assert (not (null? points)))
      (if (null? (cdr points))
          (distance p (car points))
          (max (distance p (car points))
               (max-distance-p p (cdr points)))))
    
    0 讨论(0)
提交回复
热议问题