mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 11:09:57 +00:00
Section 2.2.3
This commit is contained in:
parent
4d0dec9ac2
commit
206628f165
1 changed files with 307 additions and 0 deletions
307
2-2.org
307
2-2.org
|
@ -684,3 +684,310 @@ layout: org
|
||||||
(let ((rest (subsets (cdr s))))
|
(let ((rest (subsets (cdr s))))
|
||||||
(append rest (map (lambda (x) (cons (car s) x)) rest)))))
|
(append rest (map (lambda (x) (cons (car s) x)) rest)))))
|
||||||
#+end_src
|
#+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
|
||||||
|
|
Loading…
Reference in a new issue