【问题标题】:Scheme: Returning two largest numbers from a set of three numbers方案:从一组三个数字中返回两个最大的数字
【发布时间】:2014-09-16 02:01:04
【问题描述】:

我应该编写一个函数,打印一组给定三个数字中两个较大数字的平方和。

我处理这种情况相当笨拙。我没有编写返回一组 3 中最大的两个数字的函数,而是编写了该函数,以便表达式减少到两个所需的数字。 # SSL 函数。

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

有没有办法可以抽象出其他过程中最大数的计算?

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

【问题讨论】:

标签: scheme sicp


【解决方案1】:

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

此时书单中还没有介绍,也没有必要使用它们。这是我的解决方案(我目前正在学习 SICP 书)。

首先要找出三个数中最大的数:

(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 恰好是 比 a 和 b 都大。

第二件事是想出中间的数字:

(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 中的最大值

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

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

最后,主要功能:

(define (main a b c) 
  (sqrsum (getlargest a b c) (getmiddle a b c))
  )

我们可以通过将所有内容放入 main 中来“黑盒化”整个事情:

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

【讨论】:

  • 或者,我们不能只做(define (getsmallest a b c) (if (&lt; (if (&lt; a b) a b) c) (if (&lt; a b) a b) c)),然后对两个不是最小的整数做squaresum 吗?我认为它稍微短一些,因为我们不必同时找到最大的和中间的:)
【解决方案2】:

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

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

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

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

最后,让我们编写获得答案的过程——我们将使用applysum-square(一个接收两个参数的函数)应用于max-two(一个包含两个元素的列表)返回的结果——这就是我们如何处理max-two返回的多个值:

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

结果如预期:

(sum-max 3 1 2)
=> 13

【讨论】:

    【解决方案3】:

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


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

    1. 直接法:试图找出并计算问题中最初提出的两个较大的数字
    2. 间接方法:尝试找到并忽略唯一的最小数字,然后计算剩余的两个数字。

    我更喜欢第二种方法,因为它涉及找到一个数字,而另一种方法要求更多——我可以想象这样一个场景,我们被要求评估列表中 7 个最大数字的平方和8,例如。


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

    (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 过程上运行一些测试

    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
    

    【讨论】:

    • 这是一个好方法,但您绝对应该“选择(else (sum-of-squares x y)))”。没有理由在另外两个比较上浪费循环,使用else 可以更清楚地传达含义:cond 的这个分支只有一种可能性。但是 +1 是一种好的方法。
    【解决方案4】:

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

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

    然后测试程序

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-24
      • 1970-01-01
      • 2019-04-22
      • 2018-10-01
      • 2013-10-04
      • 1970-01-01
      • 2012-01-17
      • 2021-03-05
      相关资源
      最近更新 更多