Scheme 查找列表中两点之间的最大距离(方案)

Scheme 查找列表中两点之间的最大距离(方案),scheme,distance,Scheme,Distance,我目前正在尝试从点列表中编写一个函数,该函数返回从点p到点列表中距离p最远的点的距离。我的要点如下: ((2 . 4) (3 . 6) (5 . 12) (-4 . 3) (8.4 . 9) (0 . -1)) 我还做了一些抽象来检索一般的car和cdr(以便在代码中更容易看到),以及列表本身的car和cdr (define (get-x p) (car p) (define (get-y p) (car p) (define (get-first-point pt-list)

我目前正在尝试从点列表中编写一个函数,该函数返回从点p到点列表中距离p最远的点的距离。我的要点如下:

((2 . 4) (3 . 6) (5 . 12) (-4 . 3) (8.4 . 9) (0 . -1))
我还做了一些抽象来检索一般的car和cdr(以便在代码中更容易看到),以及列表本身的car和cdr

(define (get-x p) (car p)
(define (get-y p) (car p)


(define (get-first-point pt-list)
        (get-x pt-list))

(define (get-rest-points pt-list)
        (get-y pt-list))                                                                                         
我也已经写出了一个广义距离公式,可以用于我选择的任意两点(请记住,我将car和cdr分别抽象为get-x和get-y)

现在我有了这个,我知道我需要比较整个点集合中的各种距离,并选择最大返回值。我有一个局部解,但不是一个对每一点都正确的解

)


你可能会明白我(可怕地)试图做什么的要点,但这就是我需要帮助的原因。

get-y
应该使用
cdr
,而不是
car

get-x
get-y
缺少右括号

对于
最大距离
,我会选择

(define (max-distance p pt-list)
  (apply max (map (lambda (x) (distance p x)) pt-list)))
这意味着您不需要
获得第一个积分
获得剩余积分

图(使用(1.1)作为p):


根据您对“最远”的定义,您可能希望在表达式中包含
abs

get-y
应使用
cdr
,而不是
car

get-x
get-y
缺少右括号

对于
最大距离
,我会选择

(define (max-distance p pt-list)
  (apply max (map (lambda (x) (distance p x)) pt-list)))
这意味着您不需要
获得第一个积分
获得剩余积分

图(使用(1.1)作为p):


根据“最远”的定义,您可能希望在表达式中包含
abs

计算
点到
汽车的距离。该距离是最大距离,或者是距离
点的
cdr
的最大距离。结果是一个简单的递归算法遍历点列表

(define (max-distance-p p points)
  (if (null? points)
      0
      (max (distance p (car points))
           (max-distance-p p (cdr points)))))
如果您将
点作为空列表传入,则返回
0
;这可能有点可疑。如果是:

(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)))))

计算
点到
汽车的距离。该距离是最大距离,或者是距离
点的
cdr
的最大距离。结果是一个简单的递归算法遍历点列表

(define (max-distance-p p points)
  (if (null? points)
      0
      (max (distance p (car points))
           (max-distance-p p (cdr points)))))
如果您将
点作为空列表传入,则返回
0
;这可能有点可疑。如果是:

(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)))))

在这种情况下,您需要在点列表上添加函数f。函数f应取距离d和点x,并返回最大d和x与指定点p之间的距离。我在其他一些答案中更详细地描述了褶皱:

主要的一点是,在折叠中,您需要一个函数、一个初始值和一个列表。将函数应用于列表的第一个元素和初始值,以生成一些新值。现在,使用相同的函数、新值和列表的其余部分递归折叠。这本质上是一个类似这样的循环:

(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))
当前值=初始值
而列表不为空
当前值=使用列表的第一个元素和当前值调用函数的结果
列表=列表的其余部分
返回当前值

在这个方案中,保证尾部调用优化的就是那个循环。在您的例子中,您只需要确定初始值应该是什么,函数应该是什么。由于距离总是非负的,因此合理的初始值为零。这个函数有点复杂。当前值将是一个距离,但列表的第一个元素将是一个点。函数的结果需要一个新的距离,新的距离应该是距离当前值和列表中的某些点与特殊点之间的距离的最大值。在球拍中,这种折叠被称为,因此我们最终得到如下结果:

(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))
如果你不使用Racket,你必须自己编写
foldl
,但这并不难。(这实际上并不像Racket的
foldl
那样复杂,它可以接受任何正数的列表,但在这种情况下它会起作用。)


在这种情况下,您需要在点列表上添加函数f。函数f应取距离d和点x,并返回最大d和x与指定点p之间的距离。我在其他一些答案中更详细地描述了褶皱:

主要的一点是,在折叠中,您需要一个函数、一个初始值和一个列表。将函数应用于列表的第一个元素和初始值,以生成一些新值。现在,使用相同的函数、新值和列表的其余部分递归折叠。这本质上是一个类似这样的循环:

(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))
当前值=初始值
而列表不为空
当前值=使用列表的第一个元素和当前值调用函数的结果
列表=列表的其余部分
返回当前值

在这个方案中,保证尾部调用优化的就是那个循环。在您的例子中,您只需要确定初始值应该是什么,函数应该是什么。由于距离总是非负的,因此合理的初始值为零。这个函数有点复杂。当前值将是一个距离,但列表的第一个元素将是一个点。函数的结果需要是一个新距离,新距离应该是距离当前值和列表中某些点之间距离的最大值