diff --git a/2-2.org b/2-2.org index c07f7c0..404d980 100644 --- a/2-2.org +++ b/2-2.org @@ -684,3 +684,310 @@ layout: org (let ((rest (subsets (cdr s)))) (append rest (map (lambda (x) (cons (car s) x)) rest))))) #+end_src +* Sequences as Conventional Interfaces +** Sequence Operations + #+begin_src scheme :tangle yes + ;; =================================================================== + ;; Section 2.2.3: Sequences as Conventional Interfaces + ;; =================================================================== + (define (filter predicate sequence) + (cond ((null? sequence) nil) + ((predicate (car sequence)) + (cons (car sequence) + (filter predicate (cdr sequence)))) + (else (filter predicate (cdr sequence))))) + + (define (accumulate op initial sequence) + (if (null? sequence) + initial + (op (car sequence) + (accumulate op initial (cdr sequence))))) + + #+end_src +*** Exercise 2.33 + Fill in the missing expressions to complete the + following definitions of some basic list-manipulation operations + as accumulations: + + #+begin_src scheme + (define (map p sequence) + (accumulate (lambda (x y) ) nil sequence)) + + (define (append seq1 seq2) + (accumulate cons )) + + (define (length sequence) + (accumulate 0 sequence)) + #+end_src + + ---------------------------------------------------------------------- + + #+begin_src scheme :tangle yes + ;; ------------------------------------------------------------------- + ;; Exercise 2.33 + ;; ------------------------------------------------------------------- + + (define (map p sequence) + (accumulate (lambda (x y) (cons (p x) y)) '() sequence)) + + (define (append seq1 seq2) + (accumulate cons seq2 seq1)) + + (define (length sequence) + (accumulate (lambda (e acc) (+ 1 acc)) 0 sequence)) + #+end_src + +*** Exercise 2.34 + Evaluating a polynomial in x at a given value of + x can be formulated as an accumulation. We evaluate the polynomial + + #+begin_example + a_n r^n | a_(n-1) r^(n-1) + ... + a_1 r + a_0 + #+end_example + + using a well-known algorithm called "Horner's rule", which + structures the computation as + + #+begin_example + (... (a_n r + a_(n-1)) r + ... + a_1) r + a_0 + #+end_example + + In other words, we start with a_n, multiply by x, add a_(n-1), + multiply by x, and so on, until we reach a_0.(3) + + Fill in the following template to produce a procedure that + evaluates a polynomial using Horner's rule. Assume that the + coefficients of the polynomial are arranged in a sequence, from + a_0 through a_n. + + #+begin_src scheme + (define (horner-eval x coefficient-sequence) + (accumulate (lambda (this-coeff higher-terms) ) + 0 + coefficient-sequence)) + #+end_src + + For example, to compute 1 + 3x + 5x^3 + x^(5) at x = 2 you would + evaluate + + #+begin_src scheme + (horner-eval 2 (list 1 3 0 5 0 1)) + #+end_src + + ---------------------------------------------------------------------- + + #+begin_src scheme :tangle yes + ;; ------------------------------------------------------------------- + ;; Exercise 2.34 + ;; ------------------------------------------------------------------- + + (define (horner-eval x coefficient-sequence) + (accumulate (lambda (this-coeff higher-terms) + (+ this-coeff (* higher-terms x))) + 0 + coefficient-sequence)) + #+end_src + +*** Exercise 2.35 + Redefine `count-leaves' from section *Note 2-2-2:: as an + accumulation: + + #+begin_src scheme + (define (count-leaves t) + (accumulate (map ))) + #+end_src + + ---------------------------------------------------------------------- + + #+begin_src scheme :tangle yes + ;; ------------------------------------------------------------------- + ;; Exercise 2.35 + ;; ------------------------------------------------------------------- + + (define (count-leaves t) + (accumulate + 0 (map + (lambda (node) + (if (pair? node) + (count-leaves node) + 1)) + t))) + #+end_src + +*** Exercise 2.36 + The procedure `accumulate-n' is similar to `accumulate' except + that it takes as its third argument a sequence of sequences, which + are all assumed to have the same number of elements. It applies + the designated accumulation procedure to combine all the first + elements of the sequences, all the second elements of the + sequences, and so on, and returns a sequence of the results. For + instance, if `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': + + #+begin_src scheme + (define (accumulate-n op init seqs) + (if (null? (car seqs)) + nil + (cons (accumulate op init ) + (accumulate-n op init )))) + #+end_src + + ---------------------------------------------------------------------- + + #+begin_src scheme :tangle yes + ;; ------------------------------------------------------------------- + ;; Exercise 2.36 + ;; ------------------------------------------------------------------- + + (define (accumulate-n op init seqs) + (if (null? (car seqs)) + '() + (cons (accumulate op init (map car seqs)) + (accumulate-n op init (map cdr seqs))))) + #+end_src + +** 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 + + #+begin_example + +- -+ + | 1 2 3 4 | + | 4 5 6 6 | + | 6 7 8 9 | + +- -+ + #+end_example + + 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: + + #+begin_example + __ + (dot-product v w) returns the sum >_i v_i w_i + + (matrix-*-vector m v) returns the vector t, + __ + where t_i = >_j m_(ij) v_j + + (matrix-*-matrix m n) returns the matrix p, + __ + where p_(ij) = >_k m_(ik) n_(kj) + + (transpose m) returns the matrix n, + where n_(ij) = m_(ji) + #+end_example + + We can define the dot product as(4) + + #+begin_src scheme + (define (dot-product v w) + (accumulate + 0 (map * v w))) + #+end_src + + Fill in the missing expressions in the following procedures for + computing the other matrix operations. (The procedure `accumulate-n' + is defined in *Note Exercise 2-36::.) + + #+begin_src scheme + (define (matrix-*-vector m v) + (map m)) + + (define (transpose mat) + (accumulate-n mat)) + + (define (matrix-*-matrix m n) + (let ((cols (transpose n))) + (map m))) + #+end_src +*** 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: + + #+begin_src scheme + (define (fold-left op initial sequence) + (define (iter result rest) + (if (null? rest) + result + (iter (op result (car rest)) + (cdr rest)))) + (iter initial sequence)) + #+end_src + + 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. + + ---------------------------------------------------------------------- + + #+begin_src scheme + ;; ------------------------------------------------------------------- + ;; Exercise 2.38 + ;; ------------------------------------------------------------------- + + (define fold-right accumulate) + + (define (fold-left op initial sequence) + (define (iter result rest) + (if (null? rest) + result + (iter (op result (car rest)) + (cdr rest)))) + (iter initial sequence)) + + ;; (fold-right / 1 (list 1 2 3)) + ;; 3/2 + + ;; (fold-left / 1 (list 1 2 3)) + ;; 1/6 + + ;; (fold-right list nil (list 1 2 3)) + ;; (((() 1) 2) 3) + + ;; (fold-left list nil (list 1 2 3)) + ;; (1 (2 (3 ()))) + #+end_src + +*** Exercise 2.39 + Complete the following definitions of `reverse' + (*Note Exercise 2-18::) in terms of `fold-right' and `fold-left' + from *Note Exercise 2-38::: + + #+begin_src scheme + (define (reverse sequence) + (fold-right (lambda (x y) ) nil sequence)) + + (define (reverse sequence) + (fold-left (lambda (x y) ) nil sequence)) + #+end_src + + ---------------------------------------------------------------------- + + #+begin_src scheme :tangle yes + ;; ------------------------------------------------------------------- + ;; Exercise 2.39 + ;; ------------------------------------------------------------------- + + (define (reverse sequence) + (fold-right (lambda (x y) (append y (list x))) '() sequence)) + + (define (reverse sequence) + (fold-left (lambda (x y) (cons y x)) '() sequence)) + #+end_src