sicp-ex-1.3



<< Previous exercise (1.2) | sicp-solutions | Next exercise (1.4) >>


Exercise 1.3. Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.

 (define (square x) (* x x)) 
  
 (define (squareSum x y) (+ (square x) (square y))) 
  
 (define (sumOfLargestTwoSquared x y z) 
   (cond ((and (>= (+ x y) (+ y z)) (>= (+ x y) (+ x z))) (squareSum x y)) 
         ((and (>= (+ x z) (+ y z)) (>= (+ x z) (+ x y))) (squareSum x z)) 
         (else (squareSum y z)) 
   ) 
 ) 
 (sumOfLargestTwoSquared 1 2 3) 
 ;Value: 13 
 (sumOfLargestTwoSquared 1 1 1) 
 ;Value: 2 
 (sumOfLargestTwoSquared 1 2 2) 
 ;Value: 8 
 (sumOfLargestTwoSquared 1 1 2) 
 ;Value: 5 
 (sumOfLargestTwoSquared 1 4 3) 
 ;Value: 25 

mdsib

Here's a version with simpler logic to detect the smallest of the three values:

 (define (ssq a b) (+ (* a a) (* b b))) 
  
 (define (sumOfLargestTwoSquared x y z) 
   (cond ((and (<= x y) (<= x z)) (ssq y z)) 
         ((and (<= y x) (<= y z)) (ssq x z)) 
         (else (ssq x y)))) 

jfr

Another solution without using constructs that haven't been introduced yet

  
 (define (sum_of_squares a b) 
   (+ (* a a) (* b b))) 
  
 (define (bigger_two a b) 
   (if (> a b) 
       a 
       b)) 
  
 (define (sum_of_largest_two_squared a b c) 
   (if (> a b) 
     (sum_square a (bigger_two b c)) 
     (sum_square b (bigger_two a c)))) 

master

Another possibility (uses some language constructs that haven't been introduced yet):

  
 (define (square x) 
   (* x x)) 
  
 (define (sum-of-squares x y) 
   (+ (square x) (square y))) 
  
 (define (sum-of-squares-of-two-largest x y z) 
   (let* ((smallest (min x y z)) 
          (two-largest (remove smallest (list x y z)))) 
     (apply sum-of-squares two-largest))) 

An even simpler solution

  
 (define (square x) 
   (* x x)) 
  
 (define (sum-of-squares x y) 
   (+ (square x) (square y))) 
  
 (define (sum-of-squares-of-two-largest x y z) 
   (sum-of-squares (max x y) (max (min x y) z))) 

Another possibility

 (define (square-two-largest a b c) 
 (- (+ (* a a) (* b b) (* c c)) (* (min a b c) (min a b c)))) 
 (define (square x) (* x x)) 
 (define (sum-of-square a b) 
   (+ (square a) 
      (square b))) 
 (define (sum-square-of-two-lager a b c) 
   (- 
    (+ 
     (sum-of-square a b) 
     (square c)) 
    (square (min a b c)) 
   ) 
 ) 

Here's yet another version.

  
 (define (sum-of-squares a b) 
   (+ (* a a) (* b b))) 
  
 (define (square-of-top a b c) 
   (cond ((= a (min a b c)) (sum-of-squares b c)) 
         ((= b (min a b c)) (sum-of-squares a c)) 
         ((= c (min a b c)) (sum-of-squares a b)))) 





LisScheSic

CS 61A notes https://people.eecs.berkeley.edu/~bh/61a-pages/Solutions/week1 give one interesting recursive call implementation

 (define (sum-square-large papa mama baby) 
   (define (square x) (* x x)) 
   (cond ((> mama papa) (sum-square-large mama papa baby)) 
         ((> baby mama) (sum-square-large papa baby mama)) 
         (else (+ (square papa) (square mama))))) 

Here it just ensure the sequence is strictly decreasing, otherwise swapping 2 items found not to meet this decreasing property. Then at the most inner call `papa mama` will be the 2 larger numbers.

It also refers to one interesting link https://code.google.com/archive/p/jrm-code-project/wikis/ProgrammingArt.wiki

 (define (sum-square-largest x y z)  
   (cond  
     ;; x is smallest  
     ((and (< x y) (< x z)) (+ (* y y) (* z z)))  
     (else (sum-square-largest y z x)))) 

This works by finding the smallest number by the recursive call.

 (define (sls x y z)  
   (cond ((> z x) (sls z y x))  
         ((> z y) (sls x z y))  
         (else (+ (* x x) (* y y))))) 

This works similarly but uses swapping instead of shifting.

----------

key quote excerpt about "art" related with the above codes from the above 2nd link:

> I don't think that the short version is more artistic than the long

> The code above is art in that I wrote it for no purpose other than to communicate some humor. It is not intended to be an example of good programming any more than an Escher print is intended to be an example of an architectural plan. I wouldn't consider it fine art either.