3.69 Exercise 3.69
We can define triples similarly to how we defined pairs, constructing a new triplet by consing an element i onto a pair (j, k) as long as i <= j.
(define (triples s t u) (if (or (stream-null? s) (stream-null? t) (stream-null? u)) the-empty-stream (cons-stream (list (stream-car s) (stream-car t) (stream-car u)) (interleave (stream-map (lambda (p) (cons (stream-car s) p)) (pairs (stream-cdr t) (stream-cdr u))) (triples (stream-cdr s) (stream-cdr t) (stream-cdr u))))))
We can then find all Pythagorean triples as follows:
(define pythagorean-triples (stream-filter (lambda (triple) (let ((i (car triple)) (j (cadr triple)) (k (caddr triple))) (= (+ (square i) (square j)) (square k)))) (triples integers integers integers)))
> (display-stream (take-stream pythagorean-triples 5))
(3 4 5)
(6 8 10)
(5 12 13)
(9 12 15)
(8 15 17)
'done
However, this might not be exactly what we want, as allows non-primitive triples as well (for examples, (6, 8, 10} as well as (3, 4, 5). We can use another stream filter to account for this as well.
(define primitive-pythagorean-triples (stream-filter (lambda (triple) (let ((i (car triple)) (j (cadr triple)) (k (caddr triple))) (= 1 (gcd i (gcd j k))))) pythagorean-triples))
> (display-stream (take-stream primitive-pythagorean-triples 2))
(3 4 5)
(5 12 13)
'done