关于sicp:方案:从三个数字集中返回两个最大数字

Scheme: Returning two largest numbers from a set of three numbers

我应该写一个函数,从给定的三个数字中打印出两个更大数字的平方和。

我相当笨拙地处理了这种情况。我没有编写返回一个3中最大的两个数字的函数,而是编写了该函数,以便将表达式简化为两个所需的数字。 #SSL功能。

之所以必须这样做,是因为我无法编写可以一起返回多个值的LISP函数,也无法编写可以读取两个值作为参数的LISP函数。

是否可以通过其他方法抽象出最大数的计算?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(define
    (min a b)
    (if (> a b) b a)
)

(define
    (max a b)
    (if (< a b) b a)
)


(define
    (square a)
    ( * a a)
)



(define
    (ssl a b c)
    (+ (square (max a b)) (square (max (min a b) c)))
)


这是SICP a?¥(计算机程序的结构和解释)书中的练习1.3。

目前,书中的清单尚未介绍,因此无需使用它们。这是我的解决方案(目前我正在学习SICP书籍)。

第一件事是拿出三个数字中最大的一个:

1
2
3
(define (getlargest a b c)
  (if (> (if (> a b) a b) c) (if (> a b) a b) c)
  )

最大读取:

  • 如果a大于b,则为a,否则为b
  • 取上一步的结果,并以相同的方式将其与c进行比较。
  • 要么返回
    a和b之间的最大数字,如果c恰好是c,则返回c
    比a和b都大。

第二件事是拿出中间数字:

1
2
3
4
5
6
(define (getmiddle a b c)
  (cond ((= (getlargest a b c) a) (if (> b c) b c))
        ((= (getlargest a b c) b) (if (> a c) a c))
        ((= (getlargest a b c) c) (if (> a b) a b))
        )
  )

getmiddle读取:

  • 使用getlargest确定a或b或c是最大的数字。
  • 如果a是最大数,则将b与c进行比较,并返回b和c中的最大值;相似地,
  • 如果b是最大的,则将a与c进行比较,然后返回a和c的最大值
  • 如果c是最大的,则将a与b进行比较,并返回a和b中的最大值

现在我们需要一个函数来计算两个数字的平方和:

1
2
3
(define (sqrsum x y)
  (+ (* x x) (* y y))
  )

最后,主要功能:

1
2
3
(define (main a b c)
  (sqrsum (getlargest a b c) (getmiddle a b c))
  )

通过将所有内容放入main中,我们可以将整个事情"黑匣子":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(define (main a b c)
 (define (getlargest)
    (if (> (if (> a b) a b) c) (if (> a b) a b) c)
  )

  (define (getmiddle)
  (cond ((= (getlargest) a) (if (> b c) b c))
        ((= (getlargest) b) (if (> a c) a c))
        ((= (getlargest) c) (if (> a b) a b))
        )
  )

  (define (sqrsum x y)
    (+ (* x x) (* y y))
  )

  (sqrsum (getlargest) (getmiddle))
  )


与往常一样,将问题分解为易于解决的子问题是一个好主意;我将解释如何编写解决方案,同时我将回答您的问题。首先,让我们找出三个数字中的两个最大数字,然后将它们返回到列表中-这是一种简单,可移植的方法,可以返回多个值:

1
2
3
4
5
6
7
8
(define (max-two a b c)
  (if (>= a b)
      (if (>= b c)
          (list a b)
          (list a c))
      (if (>= a c)
          (list b a)
          (list b c))))

现在让我们编写一个过程,该过程将两个数字作为输入,将它们平方后再加上结果-这就是我们如何声明一个将多个值作为参数接收的函数的方法:

1
2
(define (sum-square x y)
  (+ (* x x) (* y y)))

最后,让我们组成获取答案的过程-我们将使用applysum-square(一个接收两个参数的函数)应用于max-two返回的结果(带有两个元素)-这是我们如何处理max-two

返回的多个值的方法

1
2
(define (sum-max a b c)
  (apply sum-square (max-two a b c)))

结果符合预期:

1
2
(sum-max 3 1 2)
=> 13

首先,此注释未解决OP \\的问题,而是解释了我的观察,并针对给定的问题提供了不同的方法。

这是我能想到的两种方法,

  • 直接方法:尝试查找和评估最初在问题中提出的两个较大数字。
  • 间接方法:尝试查找并忽略唯一的最小数字,然后评估其余两个数字。
  • 我更喜欢第二种方法,因为它涉及找到一个数字,而另一个则要多一些?我可以想象一个场景,例如,要求我们评估8个列表中的7个最大数字的平方和。

    首先,我将为最终评估定义必要的程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (define (square x)
        (* x x))

    (define (sum-of-squares x y)
        (+ (square x) (square y)))

    (define (largest2-sum-of-squares x y z)
              ;;; x is excluded
        (cond ((and (<= x y) (<= x z)) (sum-of-squares y z))
              ;;; y is excluded
              ((and (<= y x) (<= y z)) (sum-of-squares x z))
              ;;; z is excluded
              ((and (<= z x) (<= z y)) (sum-of-squares x y)))
              ;;; Note: It's also tempting to go for (else (sum-of-squares x y)))

    然后,在STk

    上的largest2-sum-of-squares过程上运行一些测试

    1
    2
    3
    4
    5
    6
    STk> (largest2-sum-of-squares 1 2 3)
    13
    STk> (largest2-sum-of-squares 1 1 3)
    10
    STk> (largest2-sum-of-squares -3 4 0)
    16


    定义一个过程,该过程以三个数字作为参数,并返回两个较大数字的平方和。尚未使用的清单。刚刚使用的定义和条件表达式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    (define (square x) (* x x))

    (define (sum-of-square x y) (+ (square x) (square y)))

    (define (largest a b c)
      (cond ((and (> a b) (> a c)) a)
            ((and (> b a) (> b c)) b)
            ((and (> c b) (> c a)) c)))

    (define (larger a b)
      (if (< a b)
          b
          a))

    (define (sum-of-two-larger-square a b c)
         (cond ((= (largest a b c) a) (sum-of-square a (larger b c)))
                ((= (largest a b c) b) (sum-of-square b (larger a c)))
                ((= (largest a b c) c) (sum-of-square c (larger a b)))) )

    然后测试程序

    1
    2
    3
    4
    5
    6
    7
    8
    (largest 1 2 3)
    (larger 1 2)
    (square 3)
    (sum-of-square 2 3)
    (two-larger-of-three 1 2 3)
    (sum-of-two-larger-square 1 2 3)
    (sum-of-two-larger-square 12 45 100)
    (sum-of-square 45 100)