Nested Mappings
We can extend the sequence paradigm to include many computations that are commonly expressed
using nested loops.
18
Consider this problem: Given a positive integer
n
, find all ordered pairs of distinct
positive integers
i
and
j
, where 1<
j
<
i
<
n
, such that
i
+
j
is prime. For example, if
n
is 6, then the pairs
are the following:
A natural way to organize this computation is to generate the sequence of all ordered pairs of positive
integers less than or equal to
n
, filter to select those pairs whose sum is prime, and then, for each pair (
i
,
j
) that passes through the filter, produce the triple (
i
,
j
,
i
+
j
).
Here is a way to generate the sequence of pairs: For each integer
i
<
n
, enumerate the integers
j
<
i
, and
for each such
i
and
j
generate the pair (
i
,
j
). In terms of sequence operations, we map along the sequence
(enumerateinterval 1 n)
. For each
i
in this sequence, we map along the sequence
(enumerateinterval 1 ( i 1))
. For each
j
in this latter sequence, we generate the pair
(list i j)
. This gives us a sequence of pairs for each
i
. Combining all the sequences for all the
i
(by accumulating with
append
) produces the required sequence of pairs:
19
(accumulate append
nil
(map (lambda (i)
(map (lambda (j) (list i j))
(enumerateinterval 1 ( i 1))))
(enumerateinterval 1 n)))
The combination of mapping and accumulating with
append
is so common in this sort of program
that we will isolate it as a separate procedure:
(define (flatmap proc seq)
(accumulate append nil (map proc seq)))
Now filter this sequence of pairs to find those whose sum is prime. The filter predicate is called for
each element of the sequence; its argument is a pair and it must extract the integers from the pair. Thus,
the predicate to apply to each element in the sequence is
(define (primesum? pair)
(prime? (+ (car pair) (cadr pair))))
Finally, generate the sequence of results by mapping over the filtered pairs using the following
procedure, which constructs a triple consisting of the two elements of the pair along with their sum:
(define (makepairsum pair)
(list (car pair) (cadr pair) (+ (car pair) (cadr pair))))
Combining all these steps yields the complete procedure:
(define (primesumpairs n)
(map makepairsum
(filter primesum?
(flatmap
(lambda (i)
(map (lambda (j) (list i j))
This preview has intentionally blurred sections. Sign up to view the full version.
View Full Document
(enumerateinterval 1 ( i 1))))
(enumerateinterval 1 n)))))
Nested mappings are also useful for sequences other than those that enumerate intervals. Suppose we
wish to generate all the permutations of a set
S
; that is, all the ways of ordering the items in the set. For
instance, the permutations of {1,2,3} are {1,2,3}, { 1,3,2}, {2,1,3}, { 2,3,1}, { 3,1,2}, and { 3,2,1}.
Here is a plan for generating the permutations of
S
: For each item
x
in
S
, recursively generate the
sequence of permutations of
S

x
,
20
and adjoin
x
to the front of each one. This yields, for each
x
in
S
,
the sequence of permutations of
S
that begin with
x
. Combining these sequences for all
x
gives all the
permutations of
S
:
21
(define (permutations s)
(if (null? s)
; empty set?
This is the end of the preview.
Sign up
to
access the rest of the document.
 Spring '11
 Haevey
 Frame, William Barton Rogers

Click to edit the document details