<< Previous exercise (3.70) | Index | Next exercise (3.72) >>


 (define (Ramanujan s) 
          (define (stream-cadr s) (stream-car (stream-cdr s))) 
          (define (stream-cddr s) (stream-cdr (stream-cdr s))) 
          (let ((scar (stream-car s)) 
                    (scadr (stream-cadr s))) 
                 (if (= (sum-triple scar) (sum-triple scadr))  
                         (cons-stream (list (sum-triple scar) scar scadr) 
                                                  (Ramanujan (stream-cddr s))) 
                         (Ramanujan (stream-cdr s))))) 
 (define (triple x) (* x x x)) 
 (define (sum-triple x) (+ (triple (car x)) (triple (cadr x)))) 
 (define Ramanujan-numbers 
         (Ramanujan (weighted-pairs integers integers sum-triple))) 
 the next five numbers are: 
 (4104 (2 16) (9 15)) 
 (13832 (2 24) (18 20)) 
 (20683 (10 27) (19 24)) 
 (32832 (4 32) (18 30)) 
 (39312 (2 34) (15 33)) 


 (define (sum-of-cubes p) 
   (+ (cube (car p)) (cube (cadr p))))  
 (define ordered-sum-of-cubes 
   (stream-map sum-of-cubes (weighted-pairs integers integers sum-of-cubes))) 
 (define (ramanujan-stream s) 
   (let ((next (stream-cdr s))) 
     (if (= (stream-car s) (stream-car next)) 
         (cons-stream (stream-car s) 
                      (ramanujan-stream next)) 
         (ramanujan-stream next)))) 
 (stream->list (ramanujan-stream ordered-sum-of-cubes) 6) 
 ;; (1729 4104 13832 20683 32832 39312) 


 (define ram-stream 
   (stream-map cadr  
               (stream-filter (lambda (x)(= (cube-weight (car x))(cadr x)))  
                  (stream-map list cube-stream (stream-cdr (stream-map cube-weight cube-stream)))))) 
 ;Wanted to do the exercise completely using stream paradigm. 


"Easy to understand" iterative version :-)

 (define (cubicSum  p) 
     (let ((i (car p)) 
           (j (cadr p))) 
       (+ (* i i i) (* j j j)))) 
 (define sortedStream (weighted-pairs cubicSum (integers 0) (integers 0))) 
 (define (ramanujan s pre) 
     (let (( num (cubicSum (stream-car s)))) 
       (cond ((= pre num) 
                         (ramanujan (stream-cdr s) num))) 
                     (ramanujan (stream-cdr s) num))))) 
 (display-stream (ramanujan sortedStream 0)) 


Small bug in meteorgan's solution: You don't want to apriori exclude the possibility of three consequent pairs all having the same weight...i.e. you dont want to recurse into the cddr in case you find a pair with equal weights, because (weight cadr) might be equal to (weight caddr)...

But this would give you the same number as the one you find with car and cadr. So we are safe to skip to cddr directly.


My solution...

The function "repeated" should be defined in chapter one I think..

 (define (get-special-number-stream different-ways) 
   (define (proc p1 p2 p3) 
     (define (sum-of-cubed x y) (+ (cube x) (cube y))) 
     (let ((p1-sum (sum-of-cubed (car p1) (cadr p1))) 
           (p2-sum (sum-of-cubed (car p2) (cadr p2))) 
           (p3-sum (sum-of-cubed (car p3) (cadr p3)))) 
       (if (and (= p2-sum p1-sum) 
                (not (= p2-sum p3-sum))) 
   (stream-filter (lambda (x) x) 
     (stream-map proc 
                 ((repeated stream-cdr (- different-ways 1)) ordered-pairs) 
                 ((repeated stream-cdr different-ways) ordered-pairs)))) 
 (define ramanujan-numbers 
   (get-special-number-stream 2)) 


 (define (ramanujan-numbers) 
     (define (cubic-sum pair) (+ (expt (car pair) 3) (expt (cadr pair) 3))) 
     (define cubic-pairs (weighted-pairs integers integers cubic-sum)) 
     (define (rec s1 s2) 
         (let ((car-s1 (stream-car s1)) 
               (car-s2 (stream-car s2))) 
             (if (= (cubic-sum car-s1) (cubic-sum car-s2)) 
                     (rec (stream-cdr s1) (stream-cdr s2))) 
                 (rec (stream-cdr s1) (stream-cdr s2))))) 
     (stream-map cubic-sum (rec (stream-cdr cubic-pairs) cubic-pairs))) 
 (show-streams 6 (ramanujan-numbers)) 
 ; (1729) 
 ; (4104) 
 ; (13832) 
 ; (20683) 
 ; (32832) 
 ; (39312) 


How about this?

 (define (sum-of-cubes x y) 
   (+ (cube x) (cube y))) 
 (define (ramanujan? x y) 
   (= (sum-of-cubes (car x) (cadr x)) 
      (sum-of-cubes (car y) (cadr y)))) 
 (define ramanujan (stream-filter (lambda (x y) (ramanujan? x y)) (weighted-pairs integers integers sum-of-cubes))) 

I don't see it could work out, since stream-filter takes single-argument function. Your stream-filter implementation would need to take and compare two consecutive pairs from weighter-pairs stream.