响应 SICP 的以下练习,
练习1.3。定义一个以三个数字作为参数的过程 并返回两个较大数字的平方和。
我写了以下(正确的)函数:
(define (square-sum-larger a b c)
(cond ((or (and (> a b) (> b c)) (and (> b a) (> a c))) (+ (* a a) (* b b)))
((or (and (> a c) (> c b)) (and (> c a) (> a b))) (+ (* a a) (* c c)))
((or (and (> b c) (> c a)) (and (> c b) (> b a))) (+ (* b b) (* c c)))))
不幸的是,这是我生命中写过的最丑陋的功能之一。我如何
(a)优雅,
(b)让它适用于任意数量的输入?
答案 0 :(得分:4)
我找到了一个优雅的解决方案(尽管它仅适用于3个输入):
(define (square-sum-larger a b c)
(+
(square (max a b))
(square (max (min a b) c))))
答案 1 :(得分:1)
如果您愿意使用图书馆的sort
功能,这将变得轻松而优雅。
(define (square-sum-larger . nums)
(define sorted (sort nums >))
(let ((a (car sorted))
(b (cadr sorted)))
(+ (* a a) (* b b))))
在上述功能中,nums
是"休息"参数,包含传递给函数的所有参数的列表。我们只是使用>
按降序对该列表进行排序,然后对结果的前两个元素进行平方。
答案 2 :(得分:1)
我不知道它是否足够优雅,但对于3参数版本,您可以使用过程抽象来减少重复:
(define (square-sum-larger a b c)
(define (square x)
(* x x))
(define (max x y)
(if (< x y) y x))
(if (< a b)
(+ (square b) (square (max a c)))
(+ (square a) (square (max b c)))))
使其适用于任意数量的输入。
(define (square-sum-larger a b . rest)
(let loop ((a (if (> a b) a b)) ;; a becomes largest of a and b
(b (if (> a b) b a)) ;; b becomes smallest of a and b
(rest rest))
(cond ((null? rest) (+ (* a a) (* b b)))
((> (car rest) a) (loop (car rest) a (cdr rest)))
((> (car rest) b) (loop a (car rest) (cdr rest)))
(else (loop a b (cdr rest))))))
使用sort
和take
的R6RS版本:
#!r6rs
(import (rnrs)
(only (srfi :1) take))
(define (square-sum-larger . rest)
(apply +
(map (lambda (x) (* x x))
(take (list-sort > rest) 2))))
答案 3 :(得分:1)
你不需要打扰你只需要找到最好的两个。
(define (max-fold L)
(if (null? L)
#f
(reduce (lambda (x y)
(if (> x y) x y))
(car L)
L)))
(define (remove-num-once x L)
(cond ((null? L) #f)
((= x (car L)) (cdr L))
(else (cons (car L) (remove-once x (cdr L))))))
(define (square-sum-larger . nums)
(let ((max (max-fold nums)))
(+ (square max)
(square (max-fold (remove-num-once max nums))))))
(square-sum-larger 1 8 7 4 5 6 9 2)
;Value: 145