2.41 Exercise 2.41
Outside the main procedure I defined a general procedure make-ordered-triples for generating ordered triples with positive integer values up to n:
(define (make-ordered-triples n) (flatmap (lambda (i) (flatmap (lambda (j) (map (lambda (k) (list i j k)) (enumerate-interval 1 n))) (enumerate-interval 1 n))) (enumerate-interval 1 n)))
This procedure uses a pattern found earlier in unique-pairs from Exercise 2.40. In the innermost procedure, a list of lists is created with map. Above this, however, nested lists are flattened with flatmap, leaving only a singly-nested list of lists at the end. flatmap can’t be used at the innermost level, of course, because it would flatten all of the lists representing the triples into one long list.
The specific filter we are asked to implement, that of finding triples with distinct values summing to s, is defined inside ordered-distinct-triples-sum (which has an unwieldly name if I’ve ever seen one...). It checks if the sum of the values of the triple equals s by accumulating + from 0, a basic pattern we’ve seen before.
(define (ordered-distinct-triples-sum n s) (define (valid-triple? s) (lambda (t) (and (= s (accumulate + 0 t)) (and (not (= (car t) (cadr t))) (not (= (car t) (caddr t))) (not (= (cadr t) (caddr t))))))) (filter (valid-triple? s) (make-ordered-triples n)))
Because we only have triples, it’s feasible to write a predicate to test if all of the elements are distinct manually, as we have done above.