Structure and Interpretation of Computer Programs



Yüklə 2,71 Mb.
Pdf görüntüsü
səhifə44/222
tarix08.08.2018
ölçüsü2,71 Mb.
#61085
1   ...   40   41   42   43   44   45   46   47   ...   222

s

 is a sequence containing four sequences

((1 2 3) (4 5 6) (7 8 9) (10 11 12)),

then the value of 

(accumulate-n + 0 s)

 should be the sequence 

(22 26 30)

. Fill in the

missing expressions in the following definition of 

accumulate-n

(define (accumulate-n op init seqs)



  (if (null? (car seqs))

      nil

      (cons (accumulate op init <??>)

            (accumulate-n op init <??>))))



Exercise 2.37.  Suppose we represent vectors v = (v

i

) as sequences of numbers, and matrices m = 

(m

ij

) as sequences of vectors (the rows of the matrix). For example, the matrix 

is represented as the sequence 

((1 2 3 4) (4 5 6 6) (6 7 8 9))

. With this representation,

we can use sequence operations to concisely express the basic matrix and vector operations. These

operations (which are described in any book on matrix algebra) are the following:

We can define the dot product as

17

 

(define (dot-product v w)



  (accumulate + 0 (map * v w)))

Fill in the missing expressions in the following procedures for computing the other matrix operations.

(The procedure 

accumulate-n

 is defined in exercise 2.36.) 

(define (matrix-*-vector m v)

  (map <??> m))

(define (transpose mat)

  (accumulate-n <??> <??> mat))

(define (matrix-*-matrix m n)

  (let ((cols (transpose n)))

    (map <??> m)))



Exercise 2.38.  The 

accumulate

 procedure is also known as 

fold-right

, because it combines

the first element of the sequence with the result of combining all the elements to the right. There is

also a 

fold-left



, which is similar to 

fold-right

, except that it combines elements working in

the opposite direction: 




(define (fold-left op initial sequence)

  (define (iter result rest)

    (if (null? rest)

        result

        (iter (op result (car rest))

              (cdr rest))))

  (iter initial sequence))

What are the values of 

(fold-right / 1 (list 1 2 3))

(fold-left / 1 (list 1 2 3))

(fold-right list nil (list 1 2 3))

(fold-left list nil (list 1 2 3))

Give a property that 

op

 should satisfy to guarantee that 



fold-right

 and 


fold-left

 will produce

the same values for any sequence. 

Exercise 2.39.   Complete the following definitions of 

reverse


 (exercise 2.18) in terms of 

fold-right

 and 

fold-left



 from exercise 2.38: 

(define (reverse sequence)

  (fold-right (lambda (x y) <??>) nil sequence))

(define (reverse sequence)

  (fold-left (lambda (x y) <??>) nil sequence))

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< jin, 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 

(ij) 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 in, 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 

(enumerate-interval 1 n)

. For each i in this sequence, we map along the sequence 

(enumerate-interval 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))




                        (enumerate-interval 1 (- i 1))))

                 (enumerate-interval 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 (prime-sum? 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 (make-pair-sum pair)

  (list (car pair) (cadr pair) (+ (car pair) (cadr pair))))

Combining all these steps yields the complete procedure: 

(define (prime-sum-pairs n)

  (map make-pair-sum

       (filter prime-sum?

               (flatmap

                (lambda (i)

                  (map (lambda (j) (list i j))

                       (enumerate-interval 1 (- i 1))))

                (enumerate-interval 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?

      (list nil)                   ; sequence containing empty set

      (flatmap (lambda (x)

                 (map (lambda (p) (cons x p))

                      (permutations (remove x s))))

               s)))

Notice how this strategy reduces the problem of generating permutations of S to the problem of

generating the permutations of sets with fewer elements than S. In the terminal case, we work our way

down to the empty list, which represents a set of no elements. For this, we generate 

(list nil)

,



Yüklə 2,71 Mb.

Dostları ilə paylaş:
1   ...   40   41   42   43   44   45   46   47   ...   222




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə