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))))
|
||||
(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
|
||||
|
|
Loading…
Reference in a new issue