├── .gitignore ├── CODE_OF_CONDUCT.md ├── Chapter1 ├── Exercise 1.08.scm ├── Exercise 1.09.scm ├── Exercise 1.10.scm ├── Exercise 1.11.scm ├── Exercise 1.12.scm ├── Exercise 1.13.scm ├── Exercise 1.14.scm ├── Exercise 1.15.scm ├── Exercise 1.16.scm ├── Exercise 1.17.scm ├── Exercise 1.18.scm ├── Exercise 1.19.scm ├── Exercise 1.20.scm ├── Exercise 1.21.scm ├── Exercise 1.22.scm ├── Exercise 1.23.scm ├── Exercise 1.24.scm ├── Exercise 1.25.scm ├── Exercise 1.26.scm ├── Exercise 1.27.scm ├── Exercise 1.28.scm ├── Exercise 1.29.scm ├── Exercise 1.30.scm ├── Exercise 1.31.scm ├── Exercise 1.32.scm ├── Exercise 1.33.scm ├── Exercise 1.34.scm ├── Exercise 1.35.scm ├── Exercise 1.36.scm ├── Exercise 1.37.scm ├── Exercise 1.38.scm ├── Exercise 1.39.scm ├── Exercise 1.40.scm ├── Exercise 1.41.scm ├── Exercise 1.42.scm ├── Exercise 1.43.scm ├── Exercise 1.44.scm ├── Exercise 1.45.scm └── Exercise 1.46.scm ├── Chapter2 ├── Exercise 2.01.scm ├── Exercise 2.02.scm ├── Exercise 2.03.scm ├── Exercise 2.04.scm ├── Exercise 2.05.scm ├── Exercise 2.06.scm ├── Exercise 2.07.scm ├── Exercise 2.08.scm ├── Exercise 2.09.scm ├── Exercise 2.10.scm ├── Exercise 2.11.scm ├── Exercise 2.12.scm ├── Exercise 2.13.scm ├── Exercise 2.14.scm ├── Exercise 2.15.scm ├── Exercise 2.16.scm ├── Exercise 2.17.scm ├── Exercise 2.18.scm ├── Exercise 2.19.scm ├── Exercise 2.20.scm ├── Exercise 2.21.scm ├── Exercise 2.22.scm ├── Exercise 2.23.scm ├── Exercise 2.24.scm ├── Exercise 2.25.scm ├── Exercise 2.26.scm ├── Exercise 2.27.scm ├── Exercise 2.28.scm ├── Exercise 2.29.scm ├── Exercise 2.30.scm ├── Exercise 2.31.scm ├── Exercise 2.32.scm ├── Exercise 2.33.scm ├── Exercise 2.34.scm ├── Exercise 2.35.scm ├── Exercise 2.36.scm ├── Exercise 2.37.scm ├── Exercise 2.38.scm ├── Exercise 2.39.scm ├── Exercise 2.40.scm ├── Exercise 2.41.scm ├── Exercise 2.42.scm ├── Exercise 2.43.scm ├── Exercise 2.44.scm ├── Exercise 2.45.scm ├── Exercise 2.46.scm ├── Exercise 2.47.scm ├── Exercise 2.48.scm ├── Exercise 2.49.scm ├── Exercise 2.50.scm ├── Exercise 2.51.scm ├── Exercise 2.52.scm ├── Exercise 2.53.scm ├── Exercise 2.54.scm ├── Exercise 2.55.scm ├── Exercise 2.56.scm ├── Exercise 2.57.scm ├── Exercise 2.58-1.scm ├── Exercise 2.58-2.scm ├── Exercise 2.59.scm ├── Exercise 2.60.scm ├── Exercise 2.61.scm ├── Exercise 2.62.scm ├── Exercise 2.63.scm ├── Exercise 2.64.scm ├── Exercise 2.65.scm ├── Exercise 2.66.scm ├── Exercise 2.67.scm ├── Exercise 2.68.scm ├── Exercise 2.69.scm ├── Exercise 2.70.scm ├── Exercise 2.71.scm ├── Exercise 2.72.scm ├── Exercise 2.73.scm ├── Exercise 2.74.scm ├── Exercise 2.75.scm ├── Exercise 2.76.scm ├── Exercise 2.77.scm ├── Exercise 2.78.scm ├── Exercise 2.79.scm ├── Exercise 2.80.scm ├── Exercise 2.81.scm ├── Exercise 2.82.scm ├── Exercise 2.83.scm ├── Exercise 2.84.scm ├── Exercise 2.85.scm ├── Exercise 2.86.scm ├── Exercise 2.87.scm ├── Exercise 2.88.scm ├── Exercise 2.89.scm ├── Exercise 2.90.scm ├── Exercise 2.91.scm ├── Exercise 2.92.scm ├── Exercise 2.93.scm ├── Exercise 2.94.scm ├── Exercise 2.95.scm ├── Exercise 2.96.scm ├── Exercise 2.97.scm ├── polynomial.scm ├── source.scm ├── test.bak └── test.scm ├── Chapter3 ├── Exercise3.01.scm ├── Exercise3.02.scm ├── Exercise3.03.scm ├── Exercise3.04.scm ├── Exercise3.05.scm ├── Exercise3.06.scm ├── Exercise3.07.scm ├── Exercise3.08.scm ├── Exercise3.09.scm ├── Exercise3.10.scm ├── Exercise3.11.scm ├── Exercise3.12.scm ├── Exercise3.13.scm ├── Exercise3.14.scm ├── Exercise3.15.scm ├── Exercise3.16.scm ├── Exercise3.17.scm ├── Exercise3.18.scm ├── Exercise3.19.scm ├── Exercise3.20.scm ├── Exercise3.21.scm ├── Exercise3.22.scm ├── Exercise3.23.scm ├── Exercise3.24.scm ├── Exercise3.25.scm ├── Exercise3.26.scm ├── Exercise3.27.scm ├── Exercise3.28.scm ├── Exercise3.29.scm ├── Exercise3.30.scm ├── Exercise3.31.scm ├── Exercise3.32.scm ├── Exercise3.33.scm ├── Exercise3.34.scm ├── Exercise3.35.scm ├── Exercise3.36.scm ├── Exercise3.37.scm ├── Exercise3.38.scm ├── Exercise3.39.scm ├── Exercise3.40.scm ├── Exercise3.41.scm ├── Exercise3.42.scm ├── Exercise3.43.scm ├── Exercise3.44.scm ├── Exercise3.45.scm ├── Exercise3.46.scm ├── Exercise3.47.scm ├── Exercise3.48.scm ├── Exercise3.49.scm ├── Exercise3.50.scm ├── Exercise3.51.scm ├── Exercise3.52.scm ├── Exercise3.53.scm ├── Exercise3.54.scm ├── Exercise3.55.scm ├── Exercise3.56.scm ├── Exercise3.57.scm ├── Exercise3.58.scm ├── Exercise3.59.scm ├── Exercise3.60.scm ├── Exercise3.61.scm ├── Exercise3.62.scm ├── Exercise3.63.scm ├── Exercise3.64.scm ├── Exercise3.65.scm ├── Exercise3.66.scm ├── Exercise3.67.scm ├── Exercise3.68.scm ├── Exercise3.69.scm ├── Exercise3.70.scm ├── Exercise3.71.scm ├── Exercise3.72.scm ├── Exercise3.73.scm ├── Exercise3.74.scm ├── Exercise3.75.scm ├── Exercise3.76.scm ├── Exercise3.77.scm ├── Exercise3.78.scm ├── Exercise3.79.scm ├── Exercise3.80.scm ├── Exercise3.81.scm ├── Exercise3.82.scm ├── connector.scm ├── constraint.scm ├── parallel-execute.scm ├── queue.scm ├── signal.scm └── stream.scm ├── Chapter4 ├── Exercise4.01.scm ├── Exercise4.02.scm ├── Exercise4.03.scm ├── Exercise4.04.scm ├── Exercise4.05.scm ├── Exercise4.06.scm ├── Exercise4.07.scm ├── Exercise4.08.scm ├── Exercise4.09.scm ├── Exercise4.10.scm ├── Exercise4.11.scm ├── Exercise4.12.scm ├── Exercise4.13.scm ├── Exercise4.14.scm ├── Exercise4.15.scm ├── Exercise4.16.scm ├── Exercise4.17.scm ├── Exercise4.18.scm ├── Exercise4.19.scm ├── Exercise4.20.scm ├── Exercise4.21.scm ├── Exercise4.22.scm ├── Exercise4.23.scm ├── Exercise4.24.scm ├── Exercise4.25.scm ├── Exercise4.26.scm ├── Exercise4.27.scm ├── Exercise4.28.scm ├── Exercise4.29.scm ├── Exercise4.30.scm ├── Exercise4.31.scm ├── Exercise4.32.scm ├── Exercise4.33.scm ├── Exercise4.34.scm ├── Exercise4.35.scm ├── Exercise4.36.scm ├── Exercise4.37.scm ├── Exercise4.38.scm ├── Exercise4.39.scm ├── Exercise4.40.scm ├── Exercise4.41.scm ├── Exercise4.42.scm ├── Exercise4.43.scm ├── Exercise4.44.scm ├── Exercise4.45.scm ├── Exercise4.46.scm ├── Exercise4.47.scm ├── Exercise4.48.scm ├── Exercise4.49.scm ├── Exercise4.50.scm ├── Exercise4.51.scm ├── Exercise4.52.scm ├── Exercise4.53.scm ├── Exercise4.54.scm ├── Exercise4.55.scm ├── Exercise4.56.scm ├── Exercise4.57.scm ├── Exercise4.58.scm ├── Exercise4.59.scm ├── Exercise4.60.scm ├── Exercise4.61.scm ├── Exercise4.62.scm ├── Exercise4.63.scm ├── Exercise4.64.scm ├── Exercise4.65.scm ├── Exercise4.66.scm ├── Exercise4.67.scm ├── Exercise4.68.scm ├── Exercise4.69.scm ├── Exercise4.70.md ├── Exercise4.71.md ├── Exercise4.72.scm ├── Exercise4.73.md ├── Exercise4.74.scm ├── Exercise4.75.scm ├── Exercise4.76.scm ├── Exercise4.77.scm ├── Exercise4.78.scm ├── Exercise4.79.scm ├── ch4-query-mceval.rkt ├── ch4-query-streams.rkt ├── ch4-query.rkt ├── ex4.03.rkt ├── ex4.table.rkt ├── lazyeval.scm ├── lazylist.scm ├── nlpparser.scm ├── prompt.scm ├── query-system.scm ├── run-interpreter.scm ├── separating.scm ├── user.scm ├── zamb.scm ├── zch4-ambeval.scm ├── zch4-mceval.scm └── zzamb.scm ├── Chapter5 ├── Exercise5.01.md ├── Exercise5.02.scm ├── Exercise5.03.md ├── Exercise5.03.scm ├── Exercise5.04.md ├── Exercise5.05.md ├── Exercise5.06.scm ├── Exercise5.07.scm ├── Exercise5.08.scm ├── Exercise5.09.scm ├── Exercise5.10.scm ├── Exercise5.11.scm ├── Exercise5.12.scm ├── Exercise5.13.scm ├── Exercise5.14.scm ├── Exercise5.15.scm ├── Exercise5.16.scm ├── Exercise5.17.scm ├── Exercise5.18.scm ├── Exercise5.19.scm ├── Exercise5.20.md ├── Exercise5.21.scm ├── Exercise5.22.scm ├── Exercise5.23.scm ├── Exercise5.24.scm ├── Exercise5.25.scm ├── Exercise5.26.scm ├── Exercise5.27.scm ├── Exercise5.28.scm ├── Exercise5.29.scm ├── Exercise5.30.scm ├── Exercise5.31.md ├── Exercise5.32.scm ├── Exercise5.33.scm ├── Exercise5.34.scm ├── Exercise5.35.scm ├── Exercise5.36.scm ├── Exercise5.37.scm ├── Exercise5.38.scm ├── Exercise5.39.scm ├── Exercise5.40.scm ├── Exercise5.41.scm ├── Exercise5.42.scm ├── Exercise5.43.scm ├── Exercise5.44.scm ├── Exercise5.45.scm ├── Exercise5.46.scm ├── Exercise5.47.scm ├── Exercise5.48.scm ├── Exercise5.49.scm ├── Exercise5.50.scm ├── ch5-regsim.scm └── compile-and-interpret.scm ├── README.md ├── material ├── allcode │ ├── ch1.scm │ ├── ch2.scm │ ├── ch2support.scm │ ├── ch2tests.scm │ ├── ch3.scm │ ├── ch3support.scm │ ├── ch4-ambeval.scm │ ├── ch4-analyzingmceval.scm │ ├── ch4-leval.scm │ ├── ch4-mceval.scm │ ├── ch4-query.scm │ ├── ch4.scm │ ├── ch5-compiler.scm │ ├── ch5-eceval-compiler.scm │ ├── ch5-eceval-support.scm │ ├── ch5-eceval.scm │ ├── ch5-regsim.scm │ ├── ch5-syntax.scm │ ├── ch5.scm │ ├── load-eceval-compiler.scm │ ├── load-eceval.scm │ └── read.md └── photos │ ├── 5.01-controller.jpg │ ├── 5.01-data-path.jpg │ ├── 5.03.1-controller.jpg │ ├── 5.03.1-data-path.jpg │ ├── 5.20 box-and-pointer.jpg │ └── Exercise 5.4 data-path.png ├── test.py └── test.scm /.gitignore: -------------------------------------------------------------------------------- 1 | *.ss~ 2 | *.ss#* 3 | .#*.ss 4 | 5 | *.scm~ 6 | *.scm#* 7 | .#*.scm 8 | 9 | compiled 10 | 11 | # mac 12 | .DS_Store 13 | .DS_Store? 14 | 15 | # vscode 16 | .vscode/ 17 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1.09.scm: -------------------------------------------------------------------------------- 1 | #lang planet neil/sicp 2 | ; Each of the following two procedures defines a method for adding two positive 3 | ; integers in terms of the procedures inc, which increments its argument by 1, 4 | ; and dec, which decrements its argument by 1. 5 | 6 | (define (+ a b) 7 | (if (= a 0) 8 | b 9 | (inc (+ (dec a) b)))) 10 | 11 | (define (+ a b) 12 | (if (= a 0) 13 | b 14 | (+ (dec a) (inc b)))) 15 | 16 | ; Using the substitution model, illustrate the process generated by each procedure in evaluating (+ 4 5). Are these processes iterative or recursive? 17 | 18 | the first one is recursive, because the status of in each evaluating is not given, because you need to do a inc on the containing (+) procedure result. 19 | where as the second one is -------------------------------------------------------------------------------- /Chapter1/Exercise 1.10.scm: -------------------------------------------------------------------------------- 1 | #lang planet neil/sicp 2 | ; Exercise 1.10: The following procedure computes a mathematical function called Ackermann’s function. 3 | 4 | (define (A x y) 5 | (cond ((= y 0) 0) 6 | ((= x 0) (* 2 y)) 7 | ((= y 1) 2) 8 | (else (A (- x 1) 9 | (A x (- y 1)))))) 10 | ; What are the values of the following expressions? 11 | 12 | (A 1 10) 13 | (A 2 4) 14 | (A 3 3) 15 | ; Consider the following procedures, where A is the procedure defined above: 16 | 17 | (define (f n) (A 0 n)) 18 | (define (g n) (A 1 n)) 19 | (define (h n) (A 2 n)) 20 | (define (k n) (* 5 n n)) 21 | ; Give concise mathematical definitions for the functions computed by the procedures f, g, and h for positive integer values of nn. For example, (k n) computes 5n25n2. -------------------------------------------------------------------------------- /Chapter1/Exercise 1.11.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.11: A function ff is defined by the rule that f(n)=nf(n) 2 | ; =n if n<3n<3 and f(n)=f(n−1)+2f(n−2)+3f(n−3)f(n)=f(n−1)+2f(n−2)+3f 3 | ; (n−3) if n≥3n≥3. Write a procedure that computes ff by means of a 4 | ; recursive process. Write a procedure that computes ff by means 5 | ; of an iterative process. 6 | #lang planet neil/sicp 7 | ; recursive 8 | (define (double x) (+ x x)) 9 | (define (triple x) (+ x x x)) 10 | 11 | (define (f n) 12 | (cond ((< n 3) n) 13 | (else (+ (f (- n 1)) 14 | (double (f (- n 2))) 15 | (triple (f (- n 3))) 16 | ))) 17 | 18 | ; iterative 19 | (define (fi n) 20 | (f-iter 2 1 0 n)) 21 | 22 | (define (f-iter a b c count) 23 | (cond ((= count 0) c) 24 | (else (f-iter (+ a (double b) (triple c)) 25 | a 26 | b 27 | (- count 1))) 28 | )) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.12.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.12: The following pattern of numbers is called Pascal’s triangle. 2 | 3 | ; 1 4 | ; 1 1 5 | ; 1 2 1 6 | ; 1 3 3 1 7 | ; 1 4 6 4 1 8 | ; . . . 9 | ; The numbers at the edge of the triangle are all 1, and each number inside the triangle is the sum of the two numbers above it.35 Write a procedure that computes elements of Pascal’s triangle by means of a recursive process. 10 | 11 | #lang planet neil/sicp 12 | 13 | (define (ps row col) 14 | (cond ((or (< row col) 15 | (< row 1) 16 | (< col 1)) 0) 17 | ((or (= col 1) 18 | (= col row)) 1) 19 | (else (+ (ps (- row 1) (- col 1)) 20 | (ps (- row 1) col))) 21 | ) 22 | ) 23 | 24 | (ps 5 6) 25 | (ps 0 1) 26 | (ps 1 -1) 27 | (display "-------------------")(newline) 28 | (ps 1 1) 29 | (ps 3 3) 30 | (ps 12 1) 31 | (display "-------------------")(newline) 32 | (ps 2 2) 33 | (ps 12 2) 34 | (ps 12 2) 35 | 36 | ;version col start from 0 37 | (define (ps row col) 38 | (cond ((or (< row (+ col 1)) 39 | (< row 1) 40 | (< col 0)) 0) 41 | ((or (= col 0) 42 | (= (+ col 1) row)) 1) 43 | (else (+ (ps (- row 1) (- col 1)) 44 | (ps (- row 1) col))) 45 | ) 46 | ) 47 | 48 | 49 | 50 | (ps 5 6) 51 | (ps 0 1) 52 | (ps 1 -1) 53 | (display "-------------------")(newline) 54 | (ps 1 0) 55 | (ps 1 0) 56 | (ps 12 11) 57 | (display "-------------------")(newline) 58 | (ps 2 2) 59 | (ps 12 2) 60 | (ps 12 2) 61 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1.13.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.13: Prove that Fib(n)Fib(n) is the closest integer to φn/5⎯⎯√φn/5, where φ=(1+5⎯⎯√)/2φ=(1+5)/2. Hint: Let ψ=(1−5⎯⎯√)/2ψ=(1−5)/2. Use induction and the definition of the Fibonacci numbers (see 1.2.2) to prove that Fib(n)=(φn−ψn)/5⎯⎯√Fib(n)=(φn−ψn)/5. -------------------------------------------------------------------------------- /Chapter1/Exercise 1.14.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.14: Draw the tree illustrating the process generated by the count-change procedure of 1.2.2 in making change for 11 cents. What are the orders of growth of the space and number of steps used by this process as the amount to be changed increases? -------------------------------------------------------------------------------- /Chapter1/Exercise 1.15.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.15: The sine of an angle (specified in radians) can be computed by making use of the approximation sinx≈xsin⁡x≈x if xx is sufficiently small, and the trigonometric identity 2 | ; sinx=3sinx3−4sin3x3 3 | ; sin⁡x=3sin⁡x3−4sin3⁡x3 4 | ; to reduce the size of the argument of sin. (For purposes of this exercise an angle is considered “sufficiently small” if its magnitude is not greater than 0.1 radians.) These ideas are incorporated in the following procedures: 5 | 6 | ; (define (cube x) (* x x x)) 7 | ; (define (p x) (- (* 3 x) (* 4 (cube x)))) 8 | ; (define (sine angle) 9 | ; (if (not (> (abs angle) 0.1)) 10 | ; angle 11 | ; (p (sine (/ angle 3.0))))) 12 | ; How many times is the procedure p applied when (sine 12.15) is evaluated? 13 | ; What is the order of growth in space and number of steps (as a function of aa) used by the process generated by the sine procedure when (sine a) is evaluated? -------------------------------------------------------------------------------- /Chapter1/Exercise 1.16.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does fast-expt. (Hint: Using the observation that (bn/2)2=(b2)n/2(bn/2)2=(b2)n/2, keep, along with the exponent nn and the base bb, an additional state variable aa, and define the state transformation in such a way that the product abnabn is unchanged from state to state. At the beginning of the process aa is taken to be 1, and the answer is given by the value of aa at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.) 2 | #lang planet neil/sicp 3 | (define (square x) (* x x)) 4 | (define (even? n) 5 | (= (remainder n 2) 0)) 6 | (define (expt-iter b counter product) 7 | (cond ((= counter 0) product) 8 | ((even? counter) (expt-iter (square b) (/ counter 2) product)) 9 | (else (expt-iter b 10 | (- counter 1) 11 | (* b product))))) 12 | 13 | 14 | (define (fast-expt b n) 15 | (expt-iter b n 1)) 16 | (fast-expt 2 100) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.17.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.17: The exponentiation algorithms in this section are based on performing exponentiation by means of repeated multiplication. In a similar way, one can perform integer multiplication by means of repeated addition. The following multiplication procedure (in which it is assumed that our language can only add, not multiply) is analogous to the expt procedure: 2 | 3 | ; (define (* a b) 4 | ; (if (= b 0) 5 | ; 0 6 | ; (+ a (* a (- b 1))))) 7 | ; This algorithm takes a number of steps that is linear in b. Now suppose we include, together with addition, operations double, which doubles an integer, and halve, which divides an (even) integer by 2. Using these, design a multiplication procedure analogous to fast-expt that uses a logarithmic number of steps. 8 | 9 | #lang planet neil/sicp 10 | (define (double x) (+ x x)) 11 | (define (halve x) (/ x 2)) 12 | (define (even? n) 13 | (= (remainder n 2) 0)) 14 | 15 | (define (mul-iter b counter product) 16 | (cond ((= counter 0) product) 17 | ((even? counter) (mul-iter (double b) (halve counter) product)) 18 | (else (mul-iter b 19 | (- counter 1) 20 | (+ b product))))) 21 | 22 | 23 | (define (mul b n) 24 | (mul-iter b n 0)) 25 | 26 | (mul 21 11100) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.18.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.18. Using the results of exercises 1.16 and 1.17, devise a procedure that generates an iterative process for multiplying two integers in terms of adding, doubling, and halving and uses a logarithmic number of steps.40 2 | 3 | 4 | #lang planet neil/sicp 5 | (define (double x) (+ x x)) 6 | (define (halve x) (/ x 2)) 7 | (define (even? n) 8 | (= (remainder n 2) 0)) 9 | 10 | (define (mul-iter b counter product) 11 | (cond ((= counter 0) product) 12 | ((even? counter) (mul-iter (double b) (halve counter) product)) 13 | (else (mul-iter b 14 | (- counter 1) 15 | (+ b product))))) 16 | 17 | 18 | (define (mul b n) 19 | (mul-iter b n 0)) 20 | 21 | (mul 21 11100) 22 | 23 | realizing that I achieve it in 1.17 -------------------------------------------------------------------------------- /Chapter1/Exercise 1.19.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.19. There is a clever algorithm for computing the Fibonacci numbers in a logarithmic number of steps. Recall the transformation of the state variables a and b in the fib-iter process of section 1.2.2: 2 | ; ab←a+b←a 3 | ; a←a+bb←a 4 | ; Call this transformation T, and observe that applying T over and over again n times, starting with 1 and 0, produces the pair Fib(n + 1) and Fib(n). In other words, the Fibonacci numbers are produced by applying Tn, the nth power of the transformation T, starting with the pair (1,0). Now consider T to be the special case of p = 0 and q = 1 in a family of transformations TpqTpq, where TpqTpq transforms the pair (a,b)(a,b) according to 5 | ; ab←bq+aq+ap←bp+aq 6 | ; a←bq+aq+apb←bp+aq 7 | ; Show that if we apply such a transformation TpqTpq twice, the effect is the same as using a single transformation Tp′q′Tp′q′ of the same form, and compute p′p′ and q′q′ in terms of pp and qq. This gives us an explicit way to square these transformations, and thus we can compute TnTn using successive squaring, as in the fast-expt procedure. Put this all together to complete the following procedure, which runs in a logarithmic number of steps:41 8 | ; #lang planet neil/sicp 9 | 10 | (define (fib n) 11 | (fib-iter 1 0 0 1 n)) 12 | 13 | (define (fib-iter a b p q count) 14 | (cond ((= count 0) b) 15 | ((even? count) 16 | (fib-iter a 17 | b 18 | (+ p q) ; compute p' 19 | (+ p (+ q q)) ; compute q' 20 | (/ count 2))) 21 | (else (fib-iter (+ (* b q) (* a q) (* a p)) 22 | (+ (* b p) (* a q)) 23 | p 24 | q 25 | (- count 1))))) 26 | 27 | (fib 111) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.20.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.20. The process that a procedure generates is of course dependent on the rules used by the interpreter. As an example, consider the iterative gcd procedure given above. Suppose we were to interpret this procedure using normal-order evaluation, as discussed in section 1.1.5. (The normal-order-evaluation rule for if is described in exercise 1.5.) Using the substitution method (for normal order), illustrate the process generated in evaluating (gcd 206 40) and indicate the remainder operations that are actually performed. How many remainder operations are actually performed in the normal-order evaluation of (gcd 206 40)? In the applicative-order evaluation? 2 | 3 | normal-order evaluation: 4 | (gcd 206 40) 5 | (gcd 40 (remainder 206 40)) 1 6 | (gcd 40 6) 7 | (gcd 6 (remainder 40 6)) 2 8 | (gcd 6 4) 9 | (gcd 4 (remainder 6 4)) 3 10 | (gcd 4 2) 11 | (gcd 4 (remainder 4 2)) 4 12 | (gcd 4 0) 13 | 4 14 | 15 | 16 | applicative-order evaluation: 17 | for (gcd a b) 18 | in the place of a and b: 19 | a grow as b, 20 | but one move behind. 21 | 22 | everytime step we evaluat b one time. 23 | until it is 0 24 | 25 | so we count each time how much steps it takes to evaluat b 26 | 27 | new b equals (remainder a b) 28 | takes the new steps to be step(newB) = step(a) + step(b) + 1 29 | we have x(n+2) = x(n+1) + x(n) 30 | begine from when 31 | x(0) = 1, x(-1) = 0 32 | x(1) = 1 33 | x(2) = 3 34 | x(3) = 5 35 | until x(4) = 9 36 | s(1~4) = 18 37 | 38 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1.21.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.21: Use the smallest-divisor procedure to find the smallest divisor of each of the following numbers: 199, 1999, 19999. 2 | #lang racket 3 | (define (square x) (* x x)) 4 | (define (smallest-divisor n) 5 | (find-divisor n 2)) 6 | (define (find-divisor n test-divisor) 7 | (cond ((> (square test-divisor) n) n) 8 | ((divides? test-divisor n) test-divisor) 9 | (else (find-divisor n (+ test-divisor 1))))) 10 | (define (divides? a b) 11 | (= (remainder b a) 0)) 12 | 13 | 14 | (smallest-divisor 199) 15 | (smallest-divisor 1999) 16 | (smallest-divisor 19999) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.25.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.25: Alyssa P. Hacker complains that we went to a lot of extra work in writing expmod. After all, she says, since we already know how to compute exponentials, we could have simply written 2 | ; Is she correct? Would this procedure serve as well for our fast prime tester? Explain. 3 | (define (expmod base exp m) 4 | (remainder (fast-expt base exp) m)) 5 | 6 | 7 | previous one mod each step reducing many unnessesary comutation -------------------------------------------------------------------------------- /Chapter1/Exercise 1.26.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.26: Louis Reasoner is having great difficulty doing Exercise 1.24. His fast-prime? test seems to run more slowly than his prime? test. Louis calls his friend Eva Lu Ator over to help. When they examine Louis’s code, they find that he has rewritten the expmod procedure to use an explicit multiplication, rather than calling square: 2 | 3 | ; (define (expmod base exp m) 4 | ; (cond ((= exp 0) 1) 5 | ; ((even? exp) 6 | ; (remainder 7 | ; (* (expmod base (/ exp 2) m) 8 | ; (expmod base (/ exp 2) m)) 9 | ; m)) 10 | ; (else 11 | ; (remainder 12 | ; (* base 13 | ; (expmod base (- exp 1) m)) 14 | ; m)))) 15 | ; “I don’t see what difference that could make,” says Louis. “I do.” says Eva. “By writing the procedure like that, you have transformed the Θ(logn)Θ(log⁡n) process into a Θ(n)Θ(n) process.” Explain. 16 | 17 | Because using square only compute (expmod base (/ exp 2) m) one in remainder, whereas write it seperately would dopulicate the comutation resulting. 18 | more specific, the it should reduce /2, but here dupulicate the *2 cancell out the bonus. -------------------------------------------------------------------------------- /Chapter1/Exercise 1.29.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.29: Simpson’s Rule is a more accurate method of numerical integration than the method illustrated above. Using Simpson’s Rule, the integral of a function ff between aa and bb is approximated as 2 | ; h3(y0+4y1+2y2+4y3+2y4+⋯+2yn−2+4yn−1+yn), 3 | ; h3(y0+4y1+2y2+4y3+2y4+⋯+2yn−2+4yn−1+yn), 4 | ; where h=(b−a)/nh=(b−a)/n, for some even integer nn, and yk=f(a+kh)yk=f(a+kh). (Increasing nn increases the accuracy of the approximation.) Define a procedure that takes as arguments ff, aa, bb, and nn and returns the value of the integral, computed using Simpson’s Rule. Use your procedure to integrate cube between 0 and 1 (with n=100n=100 and n=1000n=1000), and compare the results to those of the integral procedure shown above. 5 | 6 | #lang planet neil/sicp 7 | (define (sum term a next b) 8 | (if (> a b) 9 | 0 10 | (+ (term a) 11 | (sum term (next a) next b)))) 12 | 13 | (define (cube x) 14 | (* x x x) 15 | ) 16 | 17 | (define (integral f a b dx) 18 | (define (add-dx x) (+ x dx)) 19 | (* (sum f (+ a (/ dx 2.0)) add-dx b) 20 | dx)) 21 | 22 | 23 | (define (integralEnhance f a b n) 24 | (define h 25 | (/ (- b a) n)) 26 | 27 | (define (get-k x) 28 | (/ (- x a) h)) 29 | 30 | (define (get-ratio k) 31 | (cond 32 | ((= (remainder k n) 0) 1) 33 | ((= (remainder k 2) 0) 2) 34 | (else 4) 35 | )) 36 | 37 | (define (fx x) 38 | (* (/ h 3) (get-ratio (get-k x)) (f x))) 39 | 40 | (define (get-next x) 41 | (+ x h)) 42 | 43 | (sum fx a get-next b) 44 | ) 45 | 46 | (integral cube 0 1 0.01) 47 | (integralEnhance cube 0 1 100) 48 | (integral cube 0 1 0.001) 49 | (integralEnhance cube 0 1 1000) 50 | (integralEnhance cube 0 1 2) 51 | 52 | 0.24998750000000042 53 | 1/4 54 | 0.249999875000001 55 | 1/4 56 | 1/4 57 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1.30.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.30: The sum procedure above generates a linear recursion. The procedure can be rewritten so that the sum is performed iteratively. Show how to do this by filling in the missing expressions in the following definition: 2 | #lang planet neil/sicp 3 | (define (sum term a next b) 4 | (if (> a b) 5 | 0 6 | (+ (term a) 7 | (sum term (next a) next b)))) 8 | 9 | (define (sum-iter term a next b) 10 | (define (iter a result) 11 | (if (> a b) 12 | result 13 | (iter (next a) (+ (term a) result)))) 14 | (iter a 0)) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.34.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.34: Suppose we define the procedure 2 | 3 | ; (define (f g) (g 2)) 4 | ; Then we have 5 | 6 | ; (f square) 7 | ; 4 8 | 9 | ; (f (lambda (z) (* z (+ z 1)))) 10 | ; 6 11 | ; What happens if we (perversely) ask the interpreter to evaluate the combination (f f)? Explain. 12 | 13 | something went wrong -------------------------------------------------------------------------------- /Chapter1/Exercise 1.35.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.35: Show that the golden ratio φφ (1.2.2) is a fixed point of the transformation x↦1+1/xx↦1+1/x, and use this fact to compute φφ by means of the fixed-point procedure. 2 | #lang planet neil/sicp 3 | (define tolerence 0.00001) 4 | 5 | (define (fixedPoint f first_guess) 6 | (define (closeEnough x y) 7 | (let ((dis (abs (- x y)))) 8 | (if (< dis tolerence) 9 | true 10 | false 11 | ) 12 | ) 13 | ) 14 | (define (try old_guess) 15 | (let ((new_guess (f old_guess))) 16 | (if (closeEnough new_guess old_guess) 17 | new_guess 18 | (try new_guess)) 19 | ) 20 | ) 21 | (try first_guess) 22 | ) 23 | 24 | (define (golden_ratio_approximation x) 25 | (+ 1 (/ 1.0 x))) 26 | 27 | 28 | (fixedPoint golden_ratio_approximation 2) 29 | (fixedPoint golden_ratio_approximation 112) 30 | 1.6180327868852458 31 | 1.61803281074865 32 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1.38.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.38: In 1737, the Swiss mathematician Leonhard Euler published a memoir De Fractionibus Continuis, which included a continued fraction expansion for e-2e-2, where ee is the base of the natural logarithms. In this fraction, the NiNi are all 1, and the DiDi are successively 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, .... Write a program that uses your cont-frac procedure from Exercise 1.37 to approximate ee, based on Euler’s expansion. 2 | #lang planet neil/sicp 3 | (define (d x) 4 | (define (valued n) 5 | (if (or (= (remainder n 3) 1) 6 | (= (remainder n 3) 0) 7 | ) 8 | (* n 2) 9 | 1 10 | ) 11 | ) 12 | (valued (- x 1)) 13 | ) 14 | 15 | (define (n x) 1) 16 | 17 | (define (cont_frac_iter n d k) 18 | (define (search_frac g result) 19 | (let ((new_result (/ (n g) (+ (d g) result)))) 20 | (cond 21 | ((= g 0) result) 22 | (else (search_frac (- g 1) new_result)) 23 | ) 24 | ) 25 | ) 26 | (search_frac k 0) 27 | ) 28 | 29 | (cont_frac_iter n d 100.0) 30 | 31 | ```````` 32 | 2.859393841608222 33 | > -------------------------------------------------------------------------------- /Chapter1/Exercise 1.39.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.39: A continued fraction representation of the tangent function was published in 1770 by the German mathematician J.H. Lambert: 2 | ; tanx=x1-x23-x25-..., 3 | ; tan⁡x=x1−x23−x25−…, 4 | ; where xx is in radians. Define a procedure (tan-cf x k) that computes an approximation to the tangent function based on Lambert’s formula. k specifies the number of terms to compute, as in Exercise 1.37. 5 | 6 | #lang planet neil/sicp 7 | 8 | 9 | (define (cont_frac_iter n d k) 10 | (define (search_frac g result) 11 | (let ((new_result (/ (n g) (+ (d g) result)))) 12 | (cond 13 | ((= g 0) result) 14 | (else (search_frac (- g 1) new_result)) 15 | ) 16 | ) 17 | ) 18 | (search_frac k 0) 19 | ) 20 | 21 | (define (tan-cf x k) 22 | (define (d g) 23 | (+ (* g 2) 1) 24 | ) 25 | 26 | (define (n g) 27 | (if (= g 1) x (- 0 (* x x))) 28 | ) 29 | (cont_frac_iter n d k) 30 | ) 31 | 32 | 33 | (tan-cf 1.0 10) 34 | (tan-cf 1.0 100) 35 | (tan-cf 1.0 1000) 36 | (tan-cf 1.0 10000) 37 | 38 | ``````````````````````````````````` 39 | Welcome to DrRacket, version 6.6 [3m]. 40 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 41 | 0.3579073840656693 42 | 0.3579073840656693 43 | 0.3579073840656693 44 | 0.3579073840656693 45 | > -------------------------------------------------------------------------------- /Chapter1/Exercise 1.40.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.40: Define a procedure cubic that can be used together with the newtons-method procedure in expressions of the form 2 | 3 | ; (newtons-method (cubic a b c) 1) 4 | ; to approximate zeros of the cubic x3+ax2+bx+cx3+ax2+bx+c. 5 | 6 | #lang planet neil/sicp 7 | 8 | 9 | (define tolerance 0.00001) 10 | 11 | (define (fixed-point f first-guess) 12 | (define (close-enough? v1 v2) 13 | (< (abs (- v1 v2)) tolerance)) 14 | (define (try guess) 15 | (let ((next (f guess))) 16 | (if (close-enough? guess next) 17 | next 18 | (try next)))) 19 | (try first-guess)) 20 | 21 | (define (newtons-method g guess) 22 | 23 | (define (deriv g) 24 | (let ((dx 0.0001)) 25 | 26 | (lambda (x) 27 | (/ (- (g (+ x dx)) (g x)) 28 | dx)) 29 | ) 30 | ) 31 | 32 | (define (newton-transform g) 33 | (lambda (x) 34 | (- x (/ (g x) 35 | ((deriv g) x))))) 36 | (fixed-point 37 | (newton-transform g) 38 | guess 39 | ) 40 | ) 41 | 42 | 43 | (define (cubic a b c) 44 | (lambda (x) (+ (* x x x) (* a x x) (* b x) c)) 45 | ) 46 | 47 | (newtons-method (cubic 1 1 1) 1) 48 | 49 | Welcome to DrRacket, version 6.6 [3m]. 50 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 51 | -0.999999999999198 52 | > -------------------------------------------------------------------------------- /Chapter1/Exercise 1.41.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.41: Define a procedure double that takes a procedure of one argument as argument and returns a procedure that applies the original procedure twice. For example, if inc is a procedure that adds 1 to its argument, then (double inc) should be a procedure that adds 2. What value is returned by 2 | 3 | ; (((double (double double)) inc) 5) 4 | #lang planet neil/sicp 5 | 6 | 7 | (define (double f) 8 | (lambda (x) 9 | (f (f x)) 10 | ) 11 | ) 12 | 13 | 14 | (( (double double) inc) 5) 15 | (((double (double double)) inc) 5) 16 | 17 | `````````````````````````````````````````````````````````` 18 | 19 | Welcome to DrRacket, version 6.6 [3m]. 20 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 21 | 9 22 | 21 23 | > -------------------------------------------------------------------------------- /Chapter1/Exercise 1.42.scm: -------------------------------------------------------------------------------- 1 | 2 | ; Exercise 1.42: Let ff and gg be two one-argument functions. The composition ff after gg is defined to be the function x↦f(g(x))x↦f(g(x)). Define a procedure compose that implements composition. For example, if inc is a procedure that adds 1 to its argument, 3 | 4 | ; ((compose square inc) 6) 5 | ; 49 6 | #lang planet neil/sicp 7 | 8 | (define (square x) 9 | (* x x) 10 | ) 11 | 12 | (define (compose f g) 13 | (lambda (x) (f (g x))) 14 | ) 15 | 16 | 17 | ((compose square inc) 6) -------------------------------------------------------------------------------- /Chapter1/Exercise 1.43.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 1.43: If ff is a numerical function and nn is a positive integer, then we can form the nthnth repeated application of ff, which is defined to be the function whose value at xx is f(f(...(f(x))...))f(f(...(f(x))...)). For example, if ff is the function x↦x+1x↦x+1, then the nthnth repeated application of ff is the function x↦x+nx↦x+n. If ff is the operation of squaring a number, then the nthnth repeated application of ff is the function that raises its argument to the 2n-th2n-th power. Write a procedure that takes as inputs a procedure that computes ff and a positive integer nn and returns the procedure that computes the nthnth repeated application of ff. Your procedure should be able to be used as follows: 2 | 3 | ; ((repeated square 2) 5) 4 | ; 625 5 | ; Hint: You may find it convenient to use compose from Exercise 1.42. 6 | #lang planet neil/sicp 7 | 8 | (define (square x) 9 | (* x x) 10 | ) 11 | 12 | (define (repeated_recursive f k) 13 | (define (compose f g) 14 | (lambda (x) (f (g x))) 15 | ) 16 | (if (= 0 k) 17 | (lambda (x) x) 18 | (compose f (repeated_recursive f (- k 1))) 19 | ) 20 | ) 21 | 22 | (define (repeated f k) 23 | (define (compose f g) 24 | (lambda (x) (f (g x))) 25 | ) 26 | (define (next g) 27 | (compose f g) 28 | ) 29 | (define (iter n result) 30 | (if (= k n) 31 | result 32 | (iter (+ n 1) (next result)) 33 | ) 34 | ) 35 | (iter 1 f) 36 | ) 37 | 38 | ((repeated_recursive square 2) 5) 39 | ((repeated square 2) 5) 40 | ```````````````````````````````````````````````````````````` 41 | Welcome to DrRacket, version 6.6 [3m]. 42 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 43 | 625 44 | 625 45 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.01.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.1: Define a better version of make-rat that handles both positive and negative arguments. Make-rat should normalize the sign so that if the rational number is positive, both the numerator and denominator are positive, and if the rational number is negative, only the numerator is negative. 2 | #lang planet neil/sicp 3 | (define (make-rat n d) 4 | (let ((g (gcd n d))) 5 | (let( 6 | (new_n (/ n g)) 7 | (new_d (/ d g)) 8 | (positive_bo (> (* n d) 0)) 9 | ) 10 | (cond 11 | (positive_bo (cons (abs new_n) (abs new_d))) 12 | (else (cons (- 0 (abs new_n)) (abs new_d))) 13 | ) 14 | ) 15 | ) 16 | ) 17 | (make-rat 10 5) 18 | (make-rat -109 5) 19 | (make-rat 100 -25) 20 | (make-rat -14 -2) 21 | (make-rat 5242 42342) 22 | 23 | 24 | ````````````````````````````````````````````````` 25 | Welcome to DrRacket, version 6.6 [3m]. 26 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 27 | (mcons 2 1) 28 | (mcons -109 5) 29 | (mcons -4 1) 30 | (mcons 7 1) 31 | (mcons 2621 21171) 32 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.04.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.4: Here is an alternative procedural representation of pairs. For this representation, verify that (car (cons x y)) yields x for any objects x and y. 2 | 3 | ; (define (cons x y) 4 | ; (lambda (m) (m x y))) 5 | 6 | ; (define (car z) 7 | ; (z (lambda (p q) p))) 8 | ; What is the corresponding definition of cdr? (Hint: To verify that this works, make use of the substitution model of 1.1.5.) 9 | #lang planet neil/sicp 10 | 11 | (define (cons x y) 12 | (lambda (m) (m x y))) 13 | 14 | (define (car z) 15 | (z (lambda (p q) p))) 16 | 17 | (define (cdr z) 18 | (z (lambda (p q) q))) 19 | 20 | (define a (cons 3 2)) 21 | (car a) 22 | (cdr a) 23 | 24 | ```````````````````````````````````````````` 25 | Welcome to DrRacket, version 6.6 [3m]. 26 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 27 | 3 28 | 2 29 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.05.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.5: Show that we can represent pairs of nonnegative integers using only numbers and arithmetic operations if we represent the pair aa and bb as the integer that is the product 2a3b2a3b. Give the corresponding definitions of the procedures cons, car, and cdr. 2 | #lang planet neil/sicp 3 | (define (pow base n) 4 | (if (= n 0) 5 | 1 6 | (* base (pow base (- n 1))) 7 | ) 8 | ) 9 | (define (root x base) 10 | (if (= x 1) 11 | 0 12 | (+ (root (/ x base) base) 1) 13 | ) 14 | ) 15 | 16 | (define (cons a b) 17 | (* (pow 2 a) (pow 3 b)) 18 | ) 19 | 20 | (define (car c) 21 | (if (= 1 (gcd c 3)) 22 | (root c 2) 23 | (car (/ c 3)) 24 | ) 25 | ) 26 | 27 | (define (cdr c) 28 | (if (= 1 (gcd c 2)) 29 | (root c 3) 30 | (cdr (/ c 2)) 31 | ) 32 | ) 33 | ; for testing 34 | (define (show x y) 35 | (display x) 36 | (display " ") 37 | (display y) 38 | (newline) 39 | 40 | (define a (cons x y)) 41 | (display (car a)) 42 | (newline) 43 | (display (cdr a)) 44 | (newline) 45 | (display "```````````````````````") 46 | (newline) 47 | 48 | ) 49 | 50 | 51 | (show 1 2) 52 | (show 21 2) 53 | (show 1 22) 54 | (show 1 22) 55 | (show 121 32) 56 | (show 131 22) 57 | (show 11 212) 58 | `````````````````````````````````````````````````````````` 59 | Welcome to DrRacket, version 6.6 [3m]. 60 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 61 | 1 2 62 | 1 63 | 2 64 | ``````````````````````` 65 | 21 2 66 | 21 67 | 2 68 | ``````````````````````` 69 | 1 22 70 | 1 71 | 22 72 | ``````````````````````` 73 | 1 22 74 | 1 75 | 22 76 | ``````````````````````` 77 | 121 32 78 | 121 79 | 32 80 | ``````````````````````` 81 | 131 22 82 | 131 83 | 22 84 | ``````````````````````` 85 | 11 212 86 | 11 87 | 212 88 | ``````````````````````` -------------------------------------------------------------------------------- /Chapter2/Exercise 2.06.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.6: In case representing pairs as procedures wasn’t mind-boggling enough, consider that, in a language that can manipulate procedures, we can get by without numbers (at least insofar as nonnegative integers are concerned) by implementing 0 and the operation of adding 1 as 2 | 3 | ; (define zero (lambda (f) (lambda (x) x))) 4 | 5 | ; (define (add-1 n) 6 | ; (lambda (f) (lambda (x) (f ((n f) x))))) 7 | ; This representation is known as Church numerals, after its inventor, Alonzo Church, the logician who invented the λ-calculus. 8 | 9 | ; Define one and two directly (not in terms of zero and add-1). (Hint: Use substitution to evaluate (add-1 zero)). Give a direct definition of the addition procedure + (not in terms of repeated application of add-1). 10 | #lang planet neil/sicp 11 | (define zero (lambda (f) (lambda (x) x))) 12 | 13 | (define (add-1 n) 14 | (lambda (f) (lambda (x) (f ((n f) x))))) 15 | 16 | 17 | (define one (lambda (f) (lambda (x) (f x)))) 18 | 19 | (define two (lambda (f) (lambda (x) (f (f x))))) 20 | 21 | (define (f x) 22 | (+ x 1) 23 | ) 24 | ((zero f) 0) 25 | ((one f) 0) 26 | ((two f) 0) 27 | 28 | ```````````````````````````````````````````````````````````````````````` 29 | Welcome to DrRacket, version 6.6 [3m]. 30 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 31 | 0 32 | 1 33 | 2 34 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.07.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.7: Alyssa’s program is incomplete because she has not specified the implementation of the interval abstraction. Here is a definition of the interval constructor: 2 | 3 | ; (define (make-interval a b) (cons a b)) 4 | ; Define selectors upper-bound and lower-bound to complete the implementation. 5 | #lang planet neil/sicp 6 | 7 | (define (make_interval a b) (cons a b)) 8 | (define (upper_bound x) (car x)) 9 | (define (lower_bound x) (cdr x)) 10 | 11 | (define a 12 | (make_interval 1 2) 13 | ) 14 | (upper_bound a) 15 | (lower_bound a) 16 | ```````````````````````````````````````` 17 | Welcome to DrRacket, version 6.6 [3m]. 18 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 19 | 1 20 | 2 21 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.08.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.8: Using reasoning analogous to Alyssa’s, describe how the difference of two intervals may be computed. Define a corresponding subtraction procedure, called sub-interval. 2 | #lang planet neil/sicp 3 | 4 | (define (make_interval a b) (cons a b)) 5 | (define (upper_bound x) (car x)) 6 | (define (lower_bound x) (cdr x)) 7 | 8 | (define (sub_interval x y) 9 | (make_interval 10 | (- (upper_bound x) (lower_bound y)) 11 | (- (lower_bound x) (upper_bound y)) 12 | ) 13 | ) 14 | 15 | (define a 16 | (make_interval 1 2) 17 | ) 18 | 19 | (define b 20 | (make_interval 2 3) 21 | ) 22 | (sub_interval a b) -------------------------------------------------------------------------------- /Chapter2/Exercise 2.10.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.10: Ben Bitdiddle, an expert systems programmer, looks over Alyssa’s shoulder and comments that it is not clear what it means to divide by an interval that spans zero. Modify Alyssa’s code to check for this condition and to signal an error if it occurs. 2 | #lang planet neil/sicp 3 | 4 | (define (make_interval a b) (cons a b)) 5 | (define (upper_bound x) (car x)) 6 | (define (lower_bound x) (cdr x)) 7 | 8 | (define (mul_interval x y) 9 | (let ((p1 (* (lower_bound x) 10 | (lower_bound y))) 11 | (p2 (* (lower_bound x) 12 | (upper_bound y))) 13 | (p3 (* (upper_bound x) 14 | (lower_bound y))) 15 | (p4 (* (upper_bound x) 16 | (upper_bound y)))) 17 | (make_interval (min p1 p2 p3 p4) 18 | (max p1 p2 p3 p4)))) 19 | (define (div_interval x y) 20 | (if (< 0 (* (upper_bound y) (lower_bound y))) 21 | (mul_interval x 22 | (make_interval 23 | (/ 1.0 (upper_bound y)) 24 | (/ 1.0 (lower_bound y)))) 25 | (error "Argument crossing 0: 26 | CONS" y) 27 | ) 28 | ) 29 | 30 | 31 | (define a 32 | (make_interval 1 2) 33 | ) 34 | 35 | (define b 36 | (make_interval 2 0) 37 | ) 38 | (div_interval a b) 39 | ``````````````````````````````````````` 40 | Welcome to DrRacket, version 6.6 [3m]. 41 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 42 | . . Argument crossing 0: 43 | CONS {2 . 0} 44 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.13.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.13: Show that under the assumption of small percentage tolerances there is a simple formula for the approximate percentage tolerance of the product of two intervals in terms of the tolerances of the factors. You may simplify the problem by assuming that all numbers are positive. 2 | 3 | let 4 | tx = x * px 5 | ty = y * py 6 | 7 | (x + tx)(y + ty) 8 | 9 | x*y + y*tx + x*ty + tx*ty 10 | 11 | we have: 12 | x*y + tx*ty +- (x*ty + y*tx) 13 | 14 | x*y + tx*ty +- x*y(px+py) 15 | 16 | x*y(1 + px*py) +- x*y(px+py) 17 | 18 | pxy = (px+py)/(1 + px*py) 19 | 20 | ~ (px+py) -------------------------------------------------------------------------------- /Chapter2/Exercise 2.15.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.15: Eva Lu Ator, another user, has also noticed the different intervals computed by different but algebraically equivalent expressions. She says that a formula to compute with intervals using Alyssa’s system will produce tighter error bounds if it can be written in such a form that no variable that represents an uncertain number is repeated. Thus, she says, par2 is a “better” program for parallel resistances than par1. Is she right? Why? 2 | 3 | 4 | 5 | no, simply becasue par1 and par2 is different in interval formulation. does not surply it is better, but simply wrong for par1. -------------------------------------------------------------------------------- /Chapter2/Exercise 2.16.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.16: Explain, in general, why equivalent algebraic expressions may lead to different answers. Can you devise an interval-arithmetic package that does not have this shortcoming, or is this task impossible? (Warning: This problem is very difficult.) 2 | 3 | because of the different arithmetic result between of interval and integer。 4 | impossible, because A/A wouldn't be one if A and A is not the same , it would be one if they are the same, and the element in the equivalent algebraic expressions have to be irrelevent in interval-arithmetic while not. 5 | with +- inner in the actual cause of (x +- ux)(y +- uy), choice of +- depend on the minus and plus while ab+ac = a(b + c) you get different +- in the unfolding expressions in math in two sides of the equation which makes it unqual -------------------------------------------------------------------------------- /Chapter2/Exercise 2.17.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.17: Define a procedure last-pair that returns the list that contains only the last element of a given (nonempty) list: 2 | 3 | #lang planet neil/sicp 4 | ; Exercise 2.17: Define a procedure last-pair that returns the list that contains only the last element of a given (nonempty) list: 5 | (define (last_pair l) 6 | (if (null? (cdr l)) 7 | l 8 | (last_pair (cdr l)) 9 | ) 10 | ) 11 | 12 | (last_pair (list 23 72 149 34)) 13 | ``````````````````````````````````````` 14 | Welcome to DrRacket, version 6.6 [3m]. 15 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 16 | (mcons 34 '()) 17 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.18.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.18: Define a procedure reverse that takes a list as argument and returns a list of the same elements in reverse order: 2 | 3 | #lang planet neil/sicp 4 | (define (reverse l) 5 | (define (iter s r) 6 | (if (null? (cdr s)) 7 | (cons (car s) r) 8 | (iter (cdr s) (cons (car s) r)) 9 | ) 10 | ) 11 | (iter l nil) 12 | ) 13 | (define (reverse_recursive l) 14 | (if (null? (cdr l)) 15 | l 16 | (append (reverse_recursive (cdr l)) (list (car l))) 17 | ) 18 | ) 19 | 20 | (list 1 4 9 16 25) 21 | (reverse (list 1 4 9 16 25)) 22 | (reverse_recursive (list 1 4 9 16 25)) 23 | ; (25 16 9 4 1) 24 | ```````````````````````````` 25 | Welcome to DrRacket, version 6.6 [3m]. 26 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 27 | (mcons 1 (mcons 4 (mcons 9 (mcons 16 (mcons 25 '()))))) 28 | (mcons 25 (mcons 16 (mcons 9 (mcons 4 (mcons 1 '()))))) 29 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.21.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.21: The procedure square-list takes a list of numbers as argument and returns a list of the squares of those numbers. 2 | 3 | ; (square-list (list 1 2 3 4)) 4 | ; (1 4 9 16) 5 | ; Here are two different definitions of square-list. Complete both of them by filling in the missing expressions: 6 | #lang planet neil/sicp 7 | (define (square x) (* x x)) 8 | 9 | (define (square-list items) 10 | (if (null? items) 11 | nil 12 | (cons (square (car items)) (square-list (cdr items))))) 13 | 14 | (define (square-list-map items) 15 | (map square items) 16 | ) 17 | 18 | (square-list (list 1 2 3 4)) 19 | (square-list-map (list 1 2 3 4)) 20 | `````````````````````````````````````````````````````` 21 | Welcome to DrRacket, version 6.6 [3m]. 22 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 23 | (mcons 1 (mcons 4 (mcons 9 (mcons 16 '())))) 24 | (mcons 1 (mcons 4 (mcons 9 (mcons 16 '())))) 25 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.22.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.22: Louis Reasoner tries to rewrite the first square-list procedure of Exercise 2.21 so that it evolves an iterative process: 2 | 3 | ; (define (square-list items) 4 | ; (define (iter things answer) 5 | ; (if (null? things) 6 | ; answer 7 | ; (iter (cdr things) 8 | ; (cons (square (car things)) 9 | ; answer)))) 10 | ; (iter items nil)) 11 | ; Unfortunately, defining square-list this way produces the answer list in the reverse order of the one desired. Why? 12 | 13 | recursive is down up while iter is down-up, the upest in the downest 14 | 15 | ; Louis then tries to fix his bug by interchanging the arguments to cons: 16 | 17 | ; (define (square-list items) 18 | ; (define (iter things answer) 19 | ; (if (null? things) 20 | ; answer 21 | ; (iter (cdr things) 22 | ; (cons answer 23 | ; (square 24 | ; (car things)))))) 25 | ; (iter items nil)) 26 | ; This doesn’t work either. Explain. 27 | only make (cdr x) be the element of x, so it went wrong -------------------------------------------------------------------------------- /Chapter2/Exercise 2.23.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.23: The procedure for-each is similar to map. It takes as arguments a procedure and a list of elements. However, rather than forming a list of the results, for-each just applies the procedure to each of the elements in turn, from left to right. The values returned by applying the procedure to the elements are not used at all—for-each is used with procedures that perform an action, such as printing. For example, 2 | 3 | ; (for-each 4 | ; (lambda (x) (newline) (display x)) 5 | ; (list 57 321 88)) 6 | 7 | ; 57 8 | ; 321 9 | ; 88 10 | ; The value returned by the call to for-each (not illustrated above) can be something arbitrary, such as true. Give an implementation of for-each. 11 | #lang planet neil/sicp 12 | 13 | (define (for-each proc items) 14 | (define (iter items) 15 | (proc (car items)) 16 | (for-each proc (cdr items)) 17 | ) 18 | (if (null? items) 19 | true 20 | (iter items) 21 | ) 22 | ) 23 | 24 | (for-each 25 | (lambda (x) (newline) (display x)) 26 | (list 57 321 88)) 27 | 28 | ``````````````````````````````````````` 29 | Welcome to DrRacket, version 6.6 [3m]. 30 | Language: planet neil/sicp, with debugging; memory limit: 128 MB. 31 | 32 | 57 33 | 321 34 | 88#t 35 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.24.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.24: Suppose we evaluate the expression (list 1 (list 2 (list 3 4))). Give the result printed by the interpreter, the corresponding box-and-pointer structure, and the interpretation of this as a tree (as in Figure 2.6). 2 | (list 1 (list 2 (list 3 4))) 3 | 4 | 5 | 6 | Welcome to DrRacket, version 6.7 [3m]. 7 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 8 | {mcons 1 {mcons {mcons 2 {mcons {mcons 3 {mcons 4 '()}} '()}} '()}} 9 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.25.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.25: Give combinations of cars and cdrs that will pick 7 from each of the following lists: 2 | 3 | ; (1 3 (5 7) 9) 4 | ; ((7)) 5 | ; (1 (2 (3 (4 (5 (6 7)))))) 6 | 7 | ;fist we build the lists 8 | (define a (list 1 3 (list 5 7) 9)) 9 | 10 | (define b (list (list 7))) 11 | 12 | (define c (list 1 (list 2 (list 3 (list 4 (list 5 (list 6 7))))))) 13 | 14 | ;now we get the 7 out 15 | (car (cdaddr a)) 16 | 17 | (caar b) 18 | 19 | (cdr (cadadr (cadadr (cadadr c)))) 20 | 21 | ``````````````````````````````````````````` 22 | Welcome to DrRacket, version 6.7 [3m]. 23 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 24 | 7 25 | 7 26 | 7 27 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.26.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.26: Suppose we define x and y to be two lists: 2 | 3 | (define x (list 1 2 3)) 4 | (define y (list 4 5 6)) 5 | ; What result is printed by the interpreter in response to evaluating each of the following expressions: 6 | 7 | (append x y) 8 | (cons x y) 9 | (list x y) 10 | ;(list x y) = (cons x (cons y nil)) 11 | (cons x (cons y nil)) 12 | ```````````````````````````````````` 13 | Welcome to DrRacket, version 6.7 [3m]. 14 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 15 | {mcons 1 {mcons 2 {mcons 3 {mcons 4 {mcons 5 {mcons 6 '()}}}}}} 16 | {mcons 17 | {mcons 1 {mcons 2 {mcons 3 '()}}} 18 | {mcons 4 {mcons 5 {mcons 6 '()}}}} 19 | {mcons 20 | {mcons 1 {mcons 2 {mcons 3 '()}}} 21 | {mcons {mcons 4 {mcons 5 {mcons 6 '()}}} '()}} 22 | {mcons 23 | {mcons 1 {mcons 2 {mcons 3 '()}}} 24 | {mcons {mcons 4 {mcons 5 {mcons 6 '()}}} '()}} 25 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.27.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.27: Modify your reverse procedure of Exercise 2.18 to produce a deep-reverse procedure that takes a list as argument and returns as its value the list with its elements reversed and with all sublists deep-reversed as well. For example, 2 | (define (deep-reverse l) 3 | (cond 4 | ( 5 | (null? (cdr l)) 6 | (if (pair? (car l)) 7 | (list (deep-reverse (car l))) 8 | l 9 | ) 10 | ) 11 | ( 12 | (pair? (car l)) 13 | (append 14 | (deep-reverse (cdr l)) 15 | (list (deep-reverse (car l))) 16 | ) 17 | ) 18 | ( 19 | else 20 | (append (deep-reverse (cdr l)) (list (car l))) 21 | ) 22 | ) 23 | ) 24 | 25 | (define (deep-reverse-two l) 26 | (define (get_new_car x) 27 | (let ((cr (car x))) 28 | (list 29 | (if (pair? cr) 30 | (deep-reverse-two cr) 31 | cr 32 | ) 33 | ) 34 | ) 35 | ) 36 | (if (null? (cdr l)) 37 | (get_new_car l) 38 | (append (deep-reverse-two (cdr l)) (get_new_car l)) 39 | ) 40 | ) 41 | 42 | (define x 43 | (list (list 1 2) (list 3 4))) 44 | 45 | x 46 | ; ((1 2) (3 4)) 47 | 48 | (reverse x) 49 | ; ((3 4) (1 2)) 50 | 51 | (deep-reverse x) 52 | (deep-reverse-two x) 53 | ; ((4 3) (2 1)) 54 | 55 | 56 | ``````````````````````````````````````` 57 | Welcome to DrRacket, version 6.7 [3m]. 58 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 59 | {mcons {mcons 1 {mcons 2 '()}} {mcons {mcons 3 {mcons 4 '()}} '()}} 60 | {mcons {mcons 3 {mcons 4 '()}} {mcons {mcons 1 {mcons 2 '()}} '()}} 61 | {mcons {mcons 4 {mcons 3 '()}} {mcons {mcons 2 {mcons 1 '()}} '()}} 62 | {mcons {mcons 4 {mcons 3 '()}} {mcons {mcons 2 {mcons 1 '()}} '()}} 63 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.28.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.28: Write a procedure fringe that takes as argument a tree (represented as a list) and returns a list whose elements are all the leaves of the tree arranged in left-to-right order. For example, 2 | 3 | (define (fringe l) 4 | (define (get_new_car x) 5 | (let ((cr (car x))) 6 | (if (pair? cr) 7 | (fringe cr) 8 | (list cr) 9 | ) 10 | ) 11 | ) 12 | (if (null? (cdr l)) 13 | (get_new_car l) 14 | (append (get_new_car l) (fringe (cdr l))) 15 | ) 16 | ) 17 | 18 | 19 | 20 | 21 | 22 | (define x 23 | (list (list 1 2) (list 3 4))) 24 | 25 | 26 | (fringe x) 27 | ; (1 2 3 4) 28 | 29 | 30 | (fringe (list x x)) 31 | ; (1 2 3 4 1 2 3 4) 32 | 33 | ````````````````````````````````````````````````````````````` 34 | Welcome to DrRacket, version 6.7 [3m]. 35 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 36 | {mcons 1 {mcons 2 {mcons 3 {mcons 4 '()}}}} 37 | {mcons 38 | 1 39 | {mcons 2 {mcons 3 {mcons 4 {mcons 1 {mcons 2 {mcons 3 {mcons 4 '()}}}}}}}} 40 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.30.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.30: Define a procedure square-tree analogous to the square-list procedure of Exercise 2.21. That is, square-tree should behave as follows: 2 | 3 | ; (square-tree 4 | ; (list 1 5 | ; (list 2 (list 3 4) 5) 6 | ; (list 6 7))) 7 | ; (1 (4 (9 16) 25) (36 49)) 8 | ; Define square-tree both directly (i.e., without using any higher-order procedures) and also by using map and recursion. 9 | 10 | (define (square x) (* x x)) 11 | ;directly 12 | (define (square-tree tree) 13 | (cond 14 | ((null? tree) nil) 15 | ((not (pair? tree)) (square tree)) 16 | (else (cons (square-tree (car tree)) (square-tree (cdr tree)))) 17 | ) 18 | ) 19 | (define (square_map tree) 20 | (map 21 | (lambda (sub_tree) 22 | (cond 23 | ((null? sub_tree) nil) 24 | ((not (pair? sub_tree)) (square sub_tree)) 25 | (else (square_map sub_tree)) 26 | ) 27 | ) 28 | tree 29 | ) 30 | ) 31 | 32 | 33 | (display 34 | (square-tree 35 | (list 1 36 | (list 2 (list 3 4) 5) 37 | (list 6 7))) 38 | ) 39 | (newline) 40 | (display 41 | (square_map 42 | (list 1 43 | (list 2 (list 3 4) 5) 44 | (list 6 7))) 45 | ) 46 | 47 | Welcome to DrRacket, version 6.7 [3m]. 48 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 49 | (1 (4 (9 16) 25) (36 49)) 50 | (1 (4 (9 16) 25) (36 49)) 51 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.31.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.31: Abstract your answer to Exercise 2.30 to produce a procedure tree-map with the property that square-tree could be defined as 2 | (define (square x) (* x x)) 3 | 4 | 5 | (define (tree-map term tree) 6 | (map 7 | (lambda (sub_tree) 8 | (cond 9 | ((null? sub_tree) nil) 10 | ((not (pair? sub_tree)) (term sub_tree)) 11 | (else (tree-map term sub_tree)) 12 | ) 13 | ) 14 | tree 15 | ) 16 | ) 17 | 18 | (define (square-tree tree) 19 | (tree-map square tree)) 20 | 21 | 22 | (display 23 | (square-tree 24 | (list 1 25 | (list 2 (list 3 4) 5) 26 | (list 6 7))) 27 | ) 28 | 29 | Welcome to DrRacket, version 6.7 [3m]. 30 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 31 | (1 (4 (9 16) 25) (36 49)) 32 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.32.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.32: We can represent a set as a list of distinct elements, and we can represent the set of all subsets of the set as a list of lists. For example, if the set is (1 2 3), then the set of all subsets is (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)). Complete the following definition of a procedure that generates the set of subsets of a set and give a clear explanation of why it works: 2 | 3 | (define (subsets s) 4 | (if (null? s) 5 | (list nil) 6 | (let ((rest (subsets (cdr s)))) 7 | (append rest (map (lambda (l) (cons (car s) l)) rest))))) 8 | 9 | (define a (list 1 2 3)) 10 | (display 11 | (subsets a) 12 | ) 13 | 14 | Welcome to DrRacket, version 6.7 [3m]. 15 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 16 | (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)) 17 | > 18 | 19 | do it by with (car s) or with out -------------------------------------------------------------------------------- /Chapter2/Exercise 2.33.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.33: Fill in the missing expressions to complete the following definitions of some basic list-manipulation operations as accumulations: 2 | (define (square x) (* x x)) 3 | 4 | (define (accumulate op initial sequence) 5 | (if (null? sequence) 6 | initial 7 | (op (car sequence) 8 | (accumulate op 9 | initial 10 | (cdr sequence))))) 11 | 12 | 13 | (define (map p sequence) 14 | (accumulate (lambda (x y) 15 | (cons 16 | (p x) 17 | y 18 | ) 19 | ) 20 | nil sequence)) 21 | 22 | (define (append seq1 seq2) 23 | (accumulate cons seq2 seq1)) 24 | 25 | (define (length sequence) 26 | (accumulate (lambda (x y) 27 | (+ 28 | 1 29 | y 30 | ) 31 | ) 32 | 0 sequence)) 33 | 34 | 35 | (define a (list 1 2 3 4)) 36 | (define b (list 5 6 (list 7 8))) 37 | (length a) 38 | (length b) 39 | (display (append a b)) 40 | (newline) 41 | (display (map square a)) 42 | 43 | Welcome to DrRacket, version 6.7 [3m]. 44 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 45 | 4 46 | 3 47 | (1 2 3 4 5 6 (7 8)) 48 | (1 4 9 16) 49 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.34.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.34: Evaluating a polynomial in xx at a given value of xx can be formulated as an accumulation. We evaluate the polynomial 2 | ; anxn+an−1xn−1+⋯+a1x+a0 3 | ; anxn+an−1xn−1+⋯+a1x+a0 4 | ; using a well-known algorithm called Horner’s rule, which structures the computation as 5 | ; (…(anx+an−1)x+⋯+a1)x+a0. 6 | ; (…(anx+an−1)x+⋯+a1)x+a0. 7 | ; In other words, we start with anan, multiply by xx, add an−1an−1, multiply by xx, and so on, until we reach a0a0.82 8 | 9 | ; 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 a0a0 through anan. 10 | 11 | ; (define 12 | ; (horner-eval x coefficient-sequence) 13 | ; (accumulate 14 | ; (lambda (this-coeff higher-terms) 15 | ; ⟨??⟩) 16 | ; 0 17 | ; coefficient-sequence)) 18 | ; For example, to compute 1+3x+5x3+x51+3x+5x3+x5 at x=2x=2 you would evaluate 19 | 20 | ; (horner-eval 2 (list 1 3 0 5 0 1)) 21 | (define (accumulate op initial sequence) 22 | (if (null? sequence) 23 | initial 24 | (op (car sequence) 25 | (accumulate op 26 | initial 27 | (cdr sequence))))) 28 | 29 | 30 | (define 31 | (horner-eval x coefficient-sequence) 32 | (accumulate 33 | (lambda (this-coeff higher-terms) 34 | (+ this-coeff (* x higher-terms))) 35 | 0 36 | coefficient-sequence)) 37 | 38 | (horner-eval 2 (list 1 3 0 5 0 1)) 39 | (accumulate + 0 (list 1 6 40 32)) 40 | 41 | Welcome to DrRacket, version 6.7 [3m]. 42 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 43 | 79 44 | 79 45 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.35.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.35: Redefine count-leaves from 2.2.2 as an accumulation: 2 | 3 | ; (define (count-leaves t) 4 | ; (accumulate ⟨??⟩ ⟨??⟩ (map ⟨??⟩ ⟨??⟩))) 5 | 6 | (define (enumerate-tree tree) 7 | (cond ((null? tree) nil) 8 | ((not (pair? tree)) (list tree)) 9 | (else (append 10 | (enumerate-tree (car tree)) 11 | (enumerate-tree (cdr tree)))))) 12 | 13 | (define (accumulate op initial sequence) 14 | (if (null? sequence) 15 | initial 16 | (op (car sequence) 17 | (accumulate op 18 | initial 19 | (cdr sequence))))) 20 | 21 | 22 | (define (count-leaves t) 23 | (accumulate 24 | (lambda (x y) 25 | (+ x y) 26 | ) 27 | 0 28 | (map (lambda (subtree) 29 | (if (pair? subtree) 30 | (count-leaves subtree) 31 | 1 32 | ) 33 | ) 34 | t))) 35 | 36 | (define x (cons (list 1 2) (list 3 4))) 37 | 38 | (count-leaves x) 39 | (count-leaves (list x x)) 40 | 41 | 42 | ; Welcome to DrRacket, version 6.7 [3m]. 43 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 44 | ; 4 45 | ; 8 46 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.36.scm: -------------------------------------------------------------------------------- 1 | 2 | ; 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: 3 | 4 | (define (accumulate op initial sequence) 5 | (if (null? sequence) 6 | initial 7 | (op (car sequence) 8 | (accumulate op 9 | initial 10 | (cdr sequence))))) 11 | 12 | (define (accumulate-n op init seqs) 13 | (if (null? (car seqs)) 14 | nil 15 | (cons (accumulate op init (map (lambda (seq) (car seq)) seqs)) 16 | (accumulate-n op init (map (lambda (seq) (cdr seq)) seqs))))) 17 | 18 | 19 | (define x (list (list 1 2 3) (list 4 5 6) (list 7 8 9) (list 10 11 12))) 20 | (display (accumulate-n + 0 x)) 21 | 22 | 23 | ; Welcome to DrRacket, version 6.7 [3m]. 24 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 25 | ; (22 26 30) 26 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.39.scm: -------------------------------------------------------------------------------- 1 | 2 | ; Exercise 2.39: Complete the following definitions of reverse (Exercise 2.18) in terms of fold-right and fold-left from Exercise 2.38: 3 | 4 | ; (define (reverse sequence) 5 | ; (fold-right 6 | ; (lambda (x y) ⟨??⟩) nil sequence)) 7 | 8 | ; (define (reverse sequence) 9 | ; (fold-left 10 | ; (lambda (x y) ⟨??⟩) nil sequence)) 11 | 12 | 13 | (define (fold-left op initial sequence) 14 | (define (iter result rest) 15 | (if (null? rest) 16 | result 17 | (iter (op result (car rest)) 18 | (cdr rest)))) 19 | (iter initial sequence)) 20 | 21 | (define (fold-right op initial sequence) 22 | (if (null? sequence) 23 | initial 24 | (op (car sequence) 25 | (fold-right op 26 | initial 27 | (cdr sequence))))) 28 | 29 | (define (reverse_right sequence) 30 | (fold-right 31 | (lambda (x y) (append y (list x))) nil sequence)) 32 | 33 | (define (reverse_left sequence) 34 | (fold-left 35 | (lambda (x y) (append (list y) x)) nil sequence)) 36 | 37 | (display (list 1 4 9 16 25)) 38 | (newline) 39 | (display (reverse_right (list 1 4 9 16 25))) 40 | (newline) 41 | (display (reverse_left (list 1 4 9 16 25))) 42 | (newline) 43 | ; Welcome to DrRacket, version 6.7 [3m]. 44 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 45 | ; (1 4 9 16 25) 46 | ; (25 16 9 4 1) 47 | ; (25 16 9 4 1) 48 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.40.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.40: Define a procedure unique-pairs that, given an integer nn, generates the sequence of pairs (i,j)(i,j) with 1≤j low high) 13 | nil 14 | (cons low 15 | (enumerate-interval 16 | (+ low 1) 17 | high)))) 18 | 19 | (define (flatmap proc seq) 20 | (accumulate append nil (map proc seq))) 21 | 22 | (define (nique_pairs n) 23 | (flatmap 24 | (lambda (x) 25 | (map 26 | (lambda (y) (list x y)) 27 | (enumerate-interval 1 (- x 1)) 28 | ) 29 | ) 30 | (enumerate-interval 1 n) 31 | ) 32 | ) 33 | 34 | (display (nique_pairs 3))(newline) 35 | (display (nique_pairs 5))(newline) 36 | 37 | ; Welcome to DrRacket, version 6.7 [3m]. 38 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 39 | ; ((2 1) (3 1) (3 2)) 40 | ; ((2 1) (3 1) (3 2) (4 1) (4 2) (4 3) (5 1) (5 2) (5 3) (5 4)) 41 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.43.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.43: Louis Reasoner is having a terrible time doing Exercise 2.42. His queens procedure seems to work, but it runs extremely slowly. (Louis never does manage to wait long enough for it to solve even the 6×66×6 case.) When Louis asks Eva Lu Ator for help, she points out that he has interchanged the order of the nested mappings in the flatmap, writing it as 2 | 3 | ; (flatmap 4 | ; (lambda (new-row) 5 | ; (map (lambda (rest-of-queens) 6 | ; (adjoin-position 7 | ; new-row k rest-of-queens)) 8 | ; (queen-cols (- k 1)))) 9 | ; (enumerate-interval 1 board-size)) 10 | ; Explain why this interchange makes the program run slowly. Estimate how long it will take Louis’s program to solve the eight-queens puzzle, assuming that the program in Exercise 2.42 solves the puzzle in time TT. 11 | 12 | because you call each (queen-cols (- k 1)) board-size times,where is should be 1 time 13 | thus, your bonus time would be board-size T time. -------------------------------------------------------------------------------- /Chapter2/Exercise 2.46.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.46: A two-dimensional vector vv running from the origin to a point can be represented as a pair consisting of an xx-coordinate and a yy-coordinate. Implement a data abstraction for vectors by giving a constructor make-vect and corresponding selectors xcor-vect and ycor-vect. In terms of your selectors and constructor, implement procedures add-vect, sub-vect, and scale-vect that perform the operations vector addition, vector subtraction, and multiplying a vector by a scalar: 2 | ; (x1,y1)+(x2,y2)(x1,y1)−(x2,y2)s⋅(x,y)===(x1+x2,y1+y2),(x1−x2,y1−y2),(sx,sy). 3 | 4 | (define (make_vect x y) 5 | (list x y) 6 | ) 7 | 8 | (define (xcor_vect vect) (car vect)) 9 | (define (ycor_vect vect) (cadr vect)) 10 | (define (add_vect vect1 vect2) 11 | (map + vect1 vect2) 12 | ) 13 | 14 | (define (sub_vect vect1 vect2) 15 | (map - vect1 vect2) 16 | ) 17 | 18 | (define (scale_vect vect n) 19 | (map (lambda (v) (* v n)) vect) 20 | ) 21 | 22 | 23 | 24 | (define a (make_vect 1 2)) 25 | 26 | 27 | (define (multiplay . args) 28 | (for-each (lambda (x) (display x) (newline)) args) 29 | ) 30 | 31 | (multiplay 32 | (add_vect a a) 33 | (sub_vect a a) 34 | (scale_vect a 10) 35 | ) 36 | 37 | Welcome to DrRacket, version 6.7 [3m]. 38 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 39 | (2 4) 40 | (0 0) 41 | (10 20) 42 | > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.47.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.47: Here are two possible constructors for frames: 2 | 3 | ; (define (make-frame origin edge1 edge2) 4 | ; (list origin edge1 edge2)) 5 | 6 | ; (define (make-frame origin edge1 edge2) 7 | ; (cons origin (cons edge1 edge2))) 8 | ; For each constructor supply the appropriate selectors to produce an implementation for frames. 9 | 10 | (define (make_frame1 origin edge1 edge2) 11 | (list origin edge1 edge2)) 12 | 13 | (define (make_frame2 origin edge1 edge2) 14 | (cons origin (cons edge1 edge2))) 15 | 16 | (define (origin_frame frame) 17 | (car frame) 18 | ) 19 | (define (edge1_frame frame) 20 | (cadr frame) 21 | ) 22 | (define (edge2_frame1 frame) 23 | (caddr frame) 24 | ) 25 | (define (edge2_frame2 frame) 26 | (cddr frame) 27 | ) 28 | 29 | (define a (make_frame1 1 2 3)) 30 | (define b (make_frame2 1 2 3)) 31 | 32 | (define (multiplay . args) 33 | (for-each (lambda (x) (display x) (newline)) args) 34 | ) 35 | (multiplay 36 | a 37 | (origin_frame a) 38 | (edge1_frame a) 39 | (edge2_frame1 a) 40 | b 41 | (origin_frame b) 42 | (edge1_frame b) 43 | (edge2_frame2 b) 44 | ) 45 | 46 | Welcome to DrRacket, version 6.7 [3m]. 47 | Language: SICP (PLaneT 1.18); memory limit: 128 MB. 48 | (1 2 3) 49 | 1 50 | 2 51 | 3 52 | (1 2 . 3) 53 | 1 54 | 2 55 | 3 56 | > 57 | -------------------------------------------------------------------------------- /Chapter2/Exercise 2.48.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.48: A directed line segment in the plane can be represented as a pair of vectors—the vector running from the origin to the start-point of the segment, and the vector running from the origin to the end-point of the segment. Use your vector representation from Exercise 2.46 to define a representation for segments with a constructor make-segment and selectors start-segment and end-segment. 2 | (define (make_vect x y) 3 | (list x y) 4 | ) 5 | 6 | (define (xcor_vect vect) (car vect)) 7 | (define (ycor_vect vect) (cadr vect)) 8 | (define (add_vect vect1 vect2) 9 | (map + vect1 vect2) 10 | ) 11 | 12 | (define (sub_vect vect1 vect2) 13 | (map - vect1 vect2) 14 | ) 15 | 16 | (define (scale_vect vect n) 17 | (map (lambda (v) (* v n)) vect) 18 | ) 19 | 20 | (define (make-segment vector1 vector2) 21 | (list vector1 vector2) 22 | ) 23 | 24 | (define (start_segment seg) 25 | (car seg) 26 | ) 27 | (define (end_segment seg) 28 | (cadr seg) 29 | ) 30 | 31 | 32 | (define a (make_vect 1 2)) 33 | (define b (make_vect 2 3)) 34 | 35 | (define z (make-segment a b)) 36 | (define (multiplay . args) 37 | (for-each (lambda (x) (display x) (newline)) args) 38 | ) 39 | (multiplay 40 | a 41 | b 42 | z 43 | "start_segment:" 44 | (start_segment z) 45 | "end_segment:" 46 | (end_segment z) 47 | ) 48 | ; Welcome to DrRacket, version 6.7 [3m]. 49 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 50 | ; (1 2) 51 | ; (2 3) 52 | ; ((1 2) (2 3)) 53 | ; start_segment: 54 | ; (1 2) 55 | ; end_segment: 56 | ; (2 3) 57 | ; > 58 | -------------------------------------------------------------------------------- /Chapter2/Exercise 2.53.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.53: What would the interpreter print in response to evaluating each of the following expressions? 2 | 3 | (display (list 'a 'b 'c))(newline) 4 | ; (a b c) 5 | (display (list (list 'george)))(newline) 6 | ; ((george)) 7 | (display (cdr '((x1 x2) (y1 y2))))(newline) 8 | ; ((y1 y2)) 9 | (display (cadr '((x1 x2) (y1 y2))))(newline) 10 | ; (y1 y2) 11 | (display (pair? (car '(a short list))))(newline) 12 | ; false 13 | (display (memq 'red '((red shoes) (blue socks))))(newline) 14 | ; false 15 | (display (memq 'red '(red shoes blue socks)))(newline) 16 | ; (red shoes blue socks) 17 | 18 | ; Welcome to DrRacket, version 6.7 [3m]. 19 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 20 | ; (a b c) 21 | ; ((george)) 22 | ; ((y1 y2)) 23 | ; (y1 y2) 24 | ; #f 25 | ; #f 26 | ; (red shoes blue socks) 27 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.54.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.54: Two lists are said to be equal? if they contain equal elements arranged in the same order. For example, 2 | 3 | ; (equal? '(this is a list) 4 | ; '(this is a list)) 5 | ; is true, but 6 | 7 | ; (equal? '(this is a list) 8 | ; '(this (is a) list)) 9 | ; is false. To be more precise, we can define equal? recursively in terms of the basic eq? equality of symbols by saying that a and b are equal? if they are both symbols and the symbols are eq?, or if they are both lists such that (car a) is equal? to (car b) and (cdr a) is equal? to (cdr b). Using this idea, implement equal? as a procedure. 10 | 11 | (define (equal? a b) 12 | (if 13 | (and (and (pair? a) (pair? b)) (eq? (car a) (car b))) 14 | (equal? (cdr a) (cdr b)) 15 | (eq? a b) 16 | ) 17 | ) 18 | (equal? '(this is a list) 19 | '(this is a list)) 20 | 21 | (equal? '(this is a list) 22 | '(this (is a) list)) 23 | 24 | 25 | ; Welcome to DrRacket, version 6.7 [3m]. 26 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 27 | ; #t 28 | ; #f 29 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.55.scm: -------------------------------------------------------------------------------- 1 | 2 | ; Exercise 2.55: Eva Lu Ator types to the interpreter the expression 3 | 4 | ; (car ''abracadabra) 5 | ; To her surprise, the interpreter prints back quote. Explain. 6 | 7 | ''(ab..)= '(quote ab..) 8 | ; teke quote literrily 9 | =(quote ab..) 10 | 11 | (car ''abracadabra)=quote -------------------------------------------------------------------------------- /Chapter2/Exercise 2.59.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.59: Implement the union-set operation for the unordered-list representation of sets. 2 | 3 | (define (element-of-set? x set) 4 | (cond ((null? set) false) 5 | ((equal? x (car set)) true) 6 | (else (element-of-set? x (cdr set))))) 7 | 8 | (define (adjoin-set x set) 9 | (if (element-of-set? x set) 10 | set 11 | (cons x set))) 12 | 13 | (define (intersection-set set1 set2) 14 | (cond ((or (null? set1) (null? set2)) 15 | '()) 16 | ((element-of-set? (car set1) set2) 17 | (cons (car set1) 18 | (intersection-set (cdr set1) 19 | set2))) 20 | (else (intersection-set (cdr set1) 21 | set2)))) 22 | 23 | (define (union_set set1 set2) 24 | (if 25 | (null? set1) 26 | set2 27 | (union_set (cdr set1) (adjoin-set (car set1) set2)) 28 | ) 29 | ) 30 | 31 | (define a '(1 2 a b)) 32 | (define b '(2 3 b c)) 33 | 34 | (display (intersection-set a b))(newline) 35 | (display (union_set a b))(newline) 36 | (display a)(newline) 37 | 38 | ; Welcome to DrRacket, version 6.7 [3m]. 39 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 40 | ; (2 b) 41 | ; (a 1 2 3 b c) 42 | ; (1 2 a b) 43 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.60.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.60: We specified that a set would be represented as a list with no duplicates. Now suppose we allow duplicates. For instance, the set {1,2,3}{1,2,3} could be represented as the list (2 3 2 1 3 2 2). Design procedures element-of-set?, adjoin-set, union-set, and intersection-set that operate on this representation. How does the efficiency of each compare with the corresponding procedure for the non-duplicate representation? Are there applications for which you would use this representation in preference to the non-duplicate one? 2 | 3 | (define (element-of-set? x set) 4 | (cond ((null? set) false) 5 | ((equal? x (car set)) true) 6 | (else (element-of-set? x (cdr set))))) 7 | 8 | (define (adjoin-set x set) 9 | (cons x set) 10 | ) 11 | (define (intersection-set set1 set2) 12 | (cond ((or (null? set1) (null? set2)) 13 | '()) 14 | ((element-of-set? (car set1) set2) 15 | (cons (car set1) 16 | (intersection-set (cdr set1) 17 | set2))) 18 | (else (intersection-set (cdr set1) 19 | set2)))) 20 | 21 | (define (union_set set1 set2) 22 | (if 23 | (null? set1) 24 | set2 25 | (union_set (cdr set1) (adjoin-set (car set1) set2)) 26 | ) 27 | ) 28 | (define a '(1 2 a b)) 29 | (define b '(2 3 b c)) 30 | 31 | (display (intersection-set a b))(newline) 32 | (display (union_set a b))(newline) 33 | (display a)(newline) 34 | 35 | ;we could do it by just change the adjoin-set 36 | ; element with more frequency could be searched faster, 37 | ; not otherwise 38 | ;frequency depending one 39 | ; Welcome to DrRacket, version 6.7 [3m]. 40 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 41 | ; (2 b) 42 | ; (b a 2 1 2 3 b c) 43 | ; (1 2 a b) 44 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.61.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.61: Give an implementation of adjoin-set using the ordered representation. By analogy with element-of-set? show how to take advantage of the ordering to produce a procedure that requires on the average about half as many steps as with the unordered representation. 2 | 3 | (define (element-of-set? x set) 4 | (cond ((null? set) false) 5 | ((= x (car set)) true) 6 | ((< x (car set)) false) 7 | (else (element-of-set? x (cdr set))))) 8 | 9 | (define (element-of-set? x set) 10 | (cond ((null? set) false) 11 | ((= x (car set)) true) 12 | ((< x (car set)) false) 13 | (else (element-of-set? x (cdr set))))) 14 | 15 | (define (intersection-set set1 set2) 16 | (if (or (null? set1) (null? set2)) 17 | '() 18 | (let ((x1 (car set1)) (x2 (car set2))) 19 | (cond ((= x1 x2) 20 | (cons x1 (intersection-set 21 | (cdr set1) 22 | (cdr set2)))) 23 | ((< x1 x2) (intersection-set 24 | (cdr set1) 25 | set2)) 26 | ((< x2 x1) (intersection-set 27 | set1 28 | (cdr set2))))))) 29 | 30 | (define (adjoin-set x set) 31 | (cond 32 | ((or (null? set) (= x (car set))) set) 33 | ((< x (car set)) (cons x set)) 34 | (else (cons (car set) (adjoin x (cdr set)))) 35 | ) 36 | ) 37 | 38 | ; (define (adjoin-set x set) 39 | ; (if (element-of-set? x set) 40 | ; set 41 | ; (cons x set))) 42 | 43 | (define a '(1 2)) 44 | (define b '(2 3)) 45 | 46 | (display (intersection-set a b))(newline) 47 | ;(display (union_set a b))(newline) 48 | (display a)(newline) 49 | 50 | ; Welcome to DrRacket, version 6.7 [3m]. 51 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 52 | ; (2) 53 | ; (1 2) 54 | ; > -------------------------------------------------------------------------------- /Chapter2/Exercise 2.67.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.67: Define an encoding tree and a sample message: 2 | ; Use the decode procedure to decode the message, and give the result. 3 | (define (make-leaf symbol weight) 4 | (list 'leaf symbol weight)) 5 | (define (leaf? object) 6 | (eq? (car object) 'leaf)) 7 | (define (symbol-leaf x) (cadr x)) 8 | (define (weight-leaf x) (caddr x)) 9 | (define (left-branch tree) (car tree)) 10 | (define (right-branch tree) (cadr tree)) 11 | 12 | (define (symbols tree) 13 | (if (leaf? tree) 14 | (list (symbol-leaf tree)) 15 | (caddr tree))) 16 | 17 | (define (weight tree) 18 | (if (leaf? tree) 19 | (weight-leaf tree) 20 | (cadddr tree))) 21 | (define (make-code-tree left right) 22 | (list left 23 | right 24 | (append (symbols left) 25 | (symbols right)) 26 | (+ (weight left) (weight right)))) 27 | 28 | (define (decode bits tree) 29 | (define (decode-1 bits current-branch) 30 | (if (null? bits) 31 | '() 32 | (let ((next-branch 33 | (choose-branch 34 | (car bits) 35 | current-branch))) 36 | (if (leaf? next-branch) 37 | (cons 38 | (symbol-leaf next-branch) 39 | (decode-1 (cdr bits) tree)) 40 | (decode-1 (cdr bits) 41 | next-branch))))) 42 | (decode-1 bits tree)) 43 | 44 | (define (choose-branch bit branch) 45 | (cond ((= bit 0) (left-branch branch)) 46 | ((= bit 1) (right-branch branch)) 47 | (else (error "bad bit: 48 | CHOOSE-BRANCH" bit)))) 49 | 50 | (define sample-tree 51 | (make-code-tree 52 | (make-leaf 'A 4) 53 | (make-code-tree 54 | (make-leaf 'B 2) 55 | (make-code-tree 56 | (make-leaf 'D 1) 57 | (make-leaf 'C 1))))) 58 | 59 | 60 | 61 | (define sample-message 62 | '(0 1 1 0 0 1 0 1 0 1 1 1 0)) 63 | 64 | 65 | (display (decode sample-message sample-tree)) -------------------------------------------------------------------------------- /Chapter2/Exercise 2.71.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.71: Suppose we have a Huffman tree for an alphabet of nn symbols, and that the relative frequencies of the symbols are 1,2,4,…,2n−11,2,4,…,2n−1. Sketch the tree for n=5n=5; for n=10n=10. In such a tree (for general nn) how many bits are required to encode the most frequent symbol? The least frequent symbol? 2 | ; 1 for the most 3 | ; n-1 for the least -------------------------------------------------------------------------------- /Chapter2/Exercise 2.72.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.72: Consider the encoding procedure that you designed in Exercise 2.68. What is the order of growth in the number of steps needed to encode a symbol? Be sure to include the number of steps needed to search the symbol list at each node encountered. To answer this question in general is difficult. Consider the special case where the relative frequencies of the nn symbols are as described in Exercise 2.71, and give the order of growth (as a function of nn) of the number of steps needed to encode the most frequent and least frequent symbols in the alphabet. 2 | 3 | ; o(n^2) worst 4 | 5 | ; o(1) the best -------------------------------------------------------------------------------- /Chapter2/Exercise 2.75.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.75: Implement the constructor make-from-mag-ang in message-passing style. This procedure should be analogous to the make-from-real-imag procedure given above. 2 | 3 | (define (make-from-mag-ang x y) 4 | (define (dispatch op) 5 | (cond ((eq? op 'magnitude) x) 6 | ((eq? op 'angle) y) 7 | ((eq? op 'real-part) 8 | (* x (cos y))) 9 | ((eq? op 'real-part) 10 | (* x (sin y))) 11 | (else 12 | (error "Unknown op: 13 | make-from-mag-ang" op)))) 14 | dispatch) -------------------------------------------------------------------------------- /Chapter2/Exercise 2.76.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.76: As a large system with generic operations evolves, new types of data objects or new operations may be needed. For each of the three strategies—generic operations with explicit dispatch, data-directed style, and message-passing-style—describe the changes that must be made to a system in order to add new types or new operations. Which organization would be most appropriate for a system in which new types must often be added? Which would be most appropriate for a system in which new operations must often be added? 2 | 3 | changs making that you could just change in one place make it the most convenience to do, and base on this principle, here the answer 4 | 1 new type added the most often which carried with a set of operations, that for data directed style and message-passing, by just adding a new type packages or just type as procedure 5 | 2 as for operations, the explicit dispatch is the best. 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter2/Exercise 2.77.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 2.77: Louis Reasoner tries to evaluate the expression (magnitude z) where z is the object shown in Figure 2.24. To his surprise, instead of the answer 5 he gets an error message from apply-generic, saying there is no method for the operation magnitude on the types (complex). He shows this interaction to Alyssa P. Hacker, who says “The problem is that the complex-number selectors were never defined for complex numbers, just for polar and rectangular numbers. All you have to do to make this work is add the following to the complex package:” 2 | 3 | ; (put 'real-part '(complex) real-part) 4 | ; (put 'imag-part '(complex) imag-part) 5 | ; (put 'magnitude '(complex) magnitude) 6 | ; (put 'angle '(complex) angle) 7 | ; Describe in detail why this works. As an example, trace through all the procedures called in evaluating the expression (magnitude z) where z is the object shown in Figure 2.24. In particular, how many times is apply-generic invoked? What procedure is dispatched to in each case? 8 | 9 | (define (apply-generic op . args) 10 | (let ((type-tags (map type-tag args))) 11 | (let ((proc (get op type-tags))) 12 | (if proc 13 | (apply proc (map contents args)) 14 | (error 15 | "No method for these types: 16 | APPLY-GENERIC" 17 | (list op type-tags)))))) 18 | 19 | (magnitude z) 20 | 21 | ; 1(magnitude z) stripped out 'complex tags as zs 22 | ; 2(magnitude zs) stripped out 'rectangular or 'polar, 23 | ; each called apply-generic a time -------------------------------------------------------------------------------- /Chapter2/test.bak: -------------------------------------------------------------------------------- 1 | (+ 1 1) 2 | -------------------------------------------------------------------------------- /Chapter2/test.scm: -------------------------------------------------------------------------------- 1 | git clone https://github.com/shadowsocks/shadowsocks-libev.git 2 | cd shadowsocks-libev 3 | sudo apt-get install build-essential autoconf libtool libssl-dev 4 | ./configure && make 5 | make install 6 | 7 | 8 | 9 | vultr: 10 | 9vM.22qTG[92{4gf -------------------------------------------------------------------------------- /Chapter3/Exercise3.01.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.1: An accumulator is a procedure that is called repeatedly with a single numeric argument and accumulates its arguments into a sum. Each time it is called, it returns the currently accumulated sum. Write a procedure make-accumulator that generates accumulators, each maintaining an independent sum. The input to make-accumulator should specify the initial value of the sum; for example 2 | 3 | ; (define A (make-accumulator 5)) 4 | 5 | ; (A 10) 6 | ; 15 7 | 8 | ; (A 10) 9 | ; 25 10 | 11 | (define (make-accumulator accumulation) 12 | (lambda (x) (begin (set! accumulation 13 | (+ accumulation x)) 14 | accumulation))) 15 | 16 | 17 | (define A (make-accumulator 5)) 18 | 19 | (A 10) 20 | 15 21 | 22 | (A 10) 23 | 25 24 | 25 | ; Welcome to DrRacket, version 6.7 [3m]. 26 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 27 | ; 15 28 | ; 15 29 | ; 25 30 | ; 25 31 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.02.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.2: In software-testing applications, it is useful to be able to count the number of times a given procedure is called during the course of a computation. Write a procedure make-monitored that takes as input a procedure, f, that itself takes one input. The result returned by make-monitored is a third procedure, say mf, that keeps track of the number of times it has been called by maintaining an internal counter. If the input to mf is the special symbol how-many-calls?, then mf returns the value of the counter. If the input is the special symbol reset-count, then mf resets the counter to zero. For any other input, mf returns the result of calling f on that input and increments the counter. For instance, we could make a monitored version of the sqrt procedure: 2 | 3 | (define (make-monitored f) 4 | (let ((times 0)) 5 | (lambda (m) 6 | (cond ((eq? m 'how-many-calls?) times) 7 | ((eq? m 'reset-acount) (set! times 0)) 8 | (else (begin (set! times (+ 1 times)) 9 | (f m))))))) 10 | 11 | (define s (make-monitored sqrt)) 12 | 13 | (s 100) 14 | 10 15 | 16 | (s 'how-many-calls?) 17 | 1 18 | 19 | (s 25) 20 | 5 21 | 22 | (s 'how-many-calls?) 23 | 2 24 | 25 | (s 'reset-acount) 26 | 27 | (s 'how-many-calls?) 28 | 0 29 | 30 | 31 | ; Welcome to DrRacket, version 6.7 [3m]. 32 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 33 | ; 10 34 | ; 10 35 | ; 1 36 | ; 1 37 | ; 5 38 | ; 5 39 | ; 2 40 | ; 2 41 | ; 0 42 | ; 0 43 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.03.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.3: Modify the make-account procedure so that it creates password-protected accounts. That is, make-account should take a symbol as an additional argument, as in 2 | 3 | ; (define acc 4 | ; (make-account 100 'secret-password)) 5 | ; The resulting account object should process a request only if it is accompanied by the password with which the account was created, and should otherwise return a complaint: 6 | 7 | ; ((acc 'secret-password 'withdraw) 40) 8 | ; 60 9 | 10 | ; ((acc 'some-other-password 'deposit) 50) 11 | ; "Incorrect password" 12 | 13 | (define (make-account balance password_server) 14 | (define (withdraw amount) 15 | (if (>= balance amount) 16 | (begin (set! balance 17 | (- balance amount)) 18 | balance) 19 | "Insufficient funds")) 20 | (define (deposit amount) 21 | (set! balance (+ balance amount)) 22 | balance) 23 | (define (dispatch password m) 24 | (if (eq? password password_server) 25 | (cond ((eq? m 'withdraw) withdraw) 26 | ((eq? m 'deposit) deposit) 27 | (else (error "Unknown request: 28 | MAKE-ACCOUNT" m))) 29 | (lambda (x) "Incorrect password"))) 30 | dispatch) 31 | 32 | (define acc 33 | (make-account 100 'secret-password)) 34 | 35 | ((acc 'secret-password 'withdraw) 40) 36 | 60 37 | 38 | ((acc 'some-other-password 'deposit) 50) 39 | "Incorrect password" 40 | ; Welcome to DrRacket, version 6.7 [3m]. 41 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 42 | ; 60 43 | ; 60 44 | ; "Incorrect password" 45 | ; "Incorrect password" 46 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.06.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.6: It is useful to be able to reset a random-number generator to produce a sequence starting from a given value. Design a new rand procedure that is called with an argument that is either the symbol generate or the symbol reset and behaves as follows: (rand 'generate) produces a new random number; ((rand 'reset) ⟨new-value⟩) resets the internal state variable to the designated ⟨new-value⟩. Thus, by resetting the state, one can generate repeatable sequences. These are very handy to have when testing and debugging programs that use random numbers. 2 | #lang racket 3 | (define random-init 4 | (random 100)) 5 | (define (rand-update x) 6 | (let ((a 27) (b 26) (m 127)) 7 | (modulo (+ (* a x) b) m))) 8 | 9 | (define rand 10 | (let ((x random-init)) 11 | (lambda () (set! x (rand-update x)) x))) 12 | 13 | (define rand_test 14 | (let ((random-init 100)) 15 | (lambda (x) 16 | (cond 17 | ((eq? x 'reset) (lambda (y) (set! random-init y))) 18 | ((eq? x 'generate) (lambda () 19 | (set! random-init 20 | (rand-update random-init)) 21 | random-init)) 22 | (else (error "unknow words")))))) 23 | 24 | ((rand_test 'generate)) 25 | ((rand_test 'generate)) 26 | ((rand_test 'reset) 100) 27 | ((rand_test 'generate)) 28 | ((rand_test 'generate)) 29 | 30 | 31 | ((rand_test 'reset) 43) 32 | ((rand_test 'generate)) 33 | ((rand_test 'generate)) 34 | ((rand_test 'reset) 43) 35 | ((rand_test 'generate)) 36 | ((rand_test 'generate)) 37 | 38 | 39 | ; Welcome to DrRacket, version 6.7 [3m]. 40 | ; Language: racket, with debugging; memory limit: 128 MB. 41 | ; 59 42 | ; 95 43 | ; 59 44 | ; 95 45 | ; 44 46 | ; 71 47 | ; 44 48 | ; 71 49 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.08.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.8: When we defined the evaluation model in 1.1.3, we said that the first step in evaluating an expression is to evaluate its subexpressions. But we never specified the order in which the subexpressions should be evaluated (e.g., left to right or right to left). When we introduce assignment, the order in which the arguments to a procedure are evaluated can make a difference to the result. Define a simple procedure f such that evaluating 2 | 3 | ; (+ (f 0) (f 1)) 4 | ; will return 0 if the arguments to + are evaluated from left to right but will return 1 if the arguments are evaluated from right to left. 5 | 6 | (define (filter c) 7 | (if (= c 0) 8 | + 9 | * )) 10 | (define (maker) 11 | (let ((count 0)) 12 | (lambda (x) 13 | (let ((op (filter count))) 14 | (begin (set! count (+ count 1)) 15 | (op x 0)))))) 16 | (define f (maker)) 17 | (define g (maker)) 18 | 19 | (+ (f 0) (f 1)) 20 | (+ (g 1) (g 0)) 21 | 22 | 23 | ; Welcome to DrRacket, version 6.7 [3m]. 24 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 25 | ; 0 26 | ; 1 27 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.09.scm: -------------------------------------------------------------------------------- 1 | Exercise 3.9: In 1.2.1 we used the substitution model to analyze two procedures for computing factorials, a recursive version 2 | 3 | (define (factorial n) 4 | (if (= n 1) 5 | 1 6 | (* n (factorial (- n 1))))) 7 | and an iterative version 8 | 9 | (define (factorial n) 10 | (fact-iter 1 1 n)) 11 | 12 | (define (fact-iter product 13 | counter 14 | max-count) 15 | (if (> counter max-count) 16 | product 17 | (fact-iter (* counter product) 18 | (+ counter 1) 19 | max-count))) 20 | Show the environment structures created by evaluating (factorial 6) using each version of the factorial procedure.142 21 | 22 | 6 23 | (factorial n) 24 | ~ 25 | 6 26 | (* n (factorial (- n 1))))) 27 | ~ 28 | 5 29 | (factorial n) 30 | ....... 31 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.10.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.10: In the make-withdraw procedure, the local variable balance is created as a parameter of make-withdraw. We could also create the local state variable explicitly, using let, as follows: 2 | 3 | ; (define (make-withdraw initial-amount) 4 | ; (let ((balance initial-amount)) 5 | ; (lambda (amount) 6 | ; (if (>= balance amount) 7 | ; (begin (set! balance 8 | ; (- balance amount)) 9 | ; balance) 10 | ; "Insufficient funds")))) 11 | ; Recall from 1.3.2 that let is simply syntactic sugar for a procedure call: 12 | 13 | ; (let ((⟨var⟩ ⟨exp⟩)) ⟨body⟩) 14 | ; is interpreted as an alternate syntax for 15 | 16 | ; ((lambda (⟨var⟩) ⟨body⟩) ⟨exp⟩) 17 | ; Use the environment model to analyze this alternate version of make-withdraw, drawing figures like the ones above to illustrate the interactions 18 | 19 | ; (define W1 (make-withdraw 100)) 20 | ; (W1 50) 21 | ; (define W2 (make-withdraw 100)) 22 | ; Show that the two versions of make-withdraw create objects with the same behavior. How do the environment structures differ for the two versions? 23 | 24 | (define (make-withdraw initial-amount) 25 | (let ((balance initial-amount)) 26 | (lambda (amount) 27 | (if (>= balance amount) 28 | (begin (set! balance 29 | (- balance amount)) 30 | balance) 31 | "Insufficient funds")))) 32 | 33 | (define W1 (make-withdraw 100)) 34 | (W1 50) 35 | (define W2 (make-withdraw 100)) 36 | 37 | with just one more layer, one more call, one more binding. -------------------------------------------------------------------------------- /Chapter3/Exercise3.13.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.13: Consider the following make-cycle procedure, which uses the last-pair procedure defined in Exercise 3.12: 2 | 3 | ; (define (make-cycle x) 4 | ; (set-cdr! (last-pair x) x) 5 | ; x) 6 | ; Draw a box-and-pointer diagram that shows the structure z created by 7 | 8 | ; (define z (make-cycle (list 'a 'b 'c))) 9 | ; What happens if we try to compute (last-pair z)? 10 | 11 | +------------------------+ 12 | v | 13 | Z--->[*][*]---->[*][*]---->[*][*] 14 | | | | 15 | v v v 16 | 'a 'b 'c 17 | 18 | ;infinite loop 19 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.14.scm: -------------------------------------------------------------------------------- 1 | Exercise 3.14: The following procedure is quite useful, although obscure: 2 | 3 | (define (mystery x) 4 | (define (loop x y) 5 | (if (null? x) 6 | y 7 | (let ((temp (cdr x))) 8 | (set-cdr! x y) 9 | (loop temp x)))) 10 | (loop x '())) 11 | Loop uses the “temporary” variable temp to hold the old value of the cdr of x, since the set-cdr! on the next line destroys the cdr. Explain what mystery does in general. Suppose v is defined by (define v (list 'a 'b 'c 'd)). Draw the box-and-pointer diagram that represents the list to which v is bound. Suppose that we now evaluate (define w (mystery v)). Draw box-and-pointer diagrams that show the structures v and w after evaluating this expression. What would be printed as the values of v and w? 12 | v 13 | | 14 | V 15 | w--->[*][*]---->[*][*]---->[*][*]---->[*][/] 16 | | | | | 17 | v v v v 18 | 'd 'c 'b 'a 19 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.15.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.15: Draw box-and-pointer diagrams to explain the effect of set-to-wow! on the structures z1 and z2 above. 2 | 3 | 4 | 5 | Z1-->[*][*] 6 | | | 7 | V V 8 | x-->[*][*]->[*][/] 9 | | | 10 | V V 11 | 'wow b 12 | 13 | 14 | Z2-->[*][*]-->[*][*]-->[*][/] 15 | | v v 16 | | b 17 | | ^ 18 | +------>[*][*]-->[*][/] 19 | v 20 | 'wow 21 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.16.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.16: Ben Bitdiddle decides to write a procedure to count the number of pairs in any list structure. “It’s easy,” he reasons. “The number of pairs in any structure is the number in the car plus the number in the cdr plus one more to count the current pair.” So Ben writes the following procedure: 2 | 3 | ; (define (count-pairs x) 4 | ; (if (not (pair? x)) 5 | ; 0 6 | ; (+ (count-pairs (car x)) 7 | ; (count-pairs (cdr x)) 8 | ; 1))) 9 | ; Show that this procedure is not correct. In particular, draw box-and-pointer diagrams representing list structures made up of exactly three pairs for which Ben’s procedure would return 3; return 4; return 7; never return at all. 10 | 11 | [/][*]->[/][*]->[/][/] 12 | 13 | [*][*]->[/][*]->[/][/] 14 | | ^ 15 | +---------------+ 16 | 17 | +-------+ 18 | | v 19 | [*][*]->[*][*]->[/][/] 20 | | ^ 21 | +-------+ 22 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.17.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.17: Devise a correct version of the count-pairs procedure of Exercise 3.16 that returns the number of distinct pairs in any structure. (Hint: Traverse the structure, maintaining an auxiliary data structure that is used to keep track of which pairs have already been counted.) 2 | 3 | (define (count_pairs x) 4 | (define counted_list '()) 5 | (define (count_pairs_inner x) 6 | (cond 7 | ((not (pair? x)) 0) 8 | ((member x counted_list) 0) 9 | (else (begin (set! counted_list (cons x counted_list)) 10 | (+ (count_pairs_inner (car x)) 11 | (count_pairs_inner (cdr x)) 12 | 1))))) 13 | (count_pairs_inner x) 14 | ) 15 | 16 | (define (count_pairs_plain x) 17 | (if (not (pair? x)) 18 | 0 19 | (+ (count_pairs_plain (car x)) 20 | (count_pairs_plain (cdr x)) 21 | 1))) 22 | 23 | (define a (cons 'a 'b)) 24 | (define b (cons 'c 'd)) 25 | (define c (cons a b)) 26 | (define d (cons a c)) 27 | (count_pairs d) 28 | (count_pairs_plain d) 29 | 30 | ; Welcome to DrRacket, version 6.7 [3m]. 31 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 32 | ; 4 33 | ; 5 34 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.18.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.18: Write a procedure that examines a list and determines whether it contains a cycle, that is, whether a program that tried to find the end of the list by taking successive cdrs would go into an infinite loop. Exercise 3.13 constructed such lists. 2 | #lang planet neil/sicp 3 | (define (last-pair x) 4 | (if (null? (cdr x)) 5 | x 6 | (last-pair (cdr x)))) 7 | (define (make-cycle x) 8 | (set-cdr! (last-pair x) x) 9 | x) 10 | 11 | (define z (make-cycle (list 'a 'b 'c))) 12 | 13 | (define (cycle? x) 14 | (define marked_list '()) 15 | (define (cycle_inner x) 16 | (cond 17 | ((not (pair? x)) false) 18 | ((member x marked_list) true) 19 | (else (begin (set! marked_list (cons x marked_list)) 20 | (or (cycle_inner (cdr x)) 21 | (cycle_inner (car x))))))) 22 | 23 | 24 | (cycle_inner x)) 25 | 26 | (define x '(a b c)) 27 | (define y '(d e f)) 28 | (set-car! (cdr x) y) 29 | (set-car! x (cdr x)) 30 | (set-cdr! (last-pair y) (cdr y)) 31 | (cycle? (list 'a 'b 'c 'd)) 32 | (cycle? z) 33 | (cycle? x) 34 | (cycle? y) 35 | 36 | ; Welcome to DrRacket, version 6.7 [3m]. 37 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 38 | ; #f 39 | ; #t 40 | ; #t 41 | ; #t 42 | ; > 43 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.19.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.19: Redo Exercise 3.18 using an algorithm that takes only a constant amount of space. (This requires a very clever idea.) 2 | 3 | (define (last-pair x) 4 | (if (null? (cdr x)) 5 | x 6 | (last-pair (cdr x)))) 7 | (define (make-cycle x) 8 | (set-cdr! (last-pair x) x) 9 | x) 10 | 11 | (define z (make-cycle (list 'a 'b 'c))) 12 | 13 | (define (cycle? x) 14 | (define (safe-cdr l) 15 | (if (pair? l) 16 | (cdr l) 17 | '())) 18 | (define (iter slow fast) 19 | (cond ((not (pair? slow)) #f) 20 | ((not (pair? fast)) #f) 21 | ((eq? slow fast) #t) 22 | (else (iter (safe-cdr slow) (safe-cdr (safe-cdr fast)))))) 23 | (iter (safe-cdr x) (safe-cdr (safe-cdr x)))) 24 | (cycle? (list 'a 'b 'c 'd)) 25 | (cycle? z) 26 | 27 | ; Welcome to DrRacket, version 6.7 [3m]. 28 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 29 | ; #f 30 | ; #t 31 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.28.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.28: Define an or-gate as a primitive function box. Your or-gate constructor should be similar to and-gate. 2 | (load "/home/soulomoon/git/SICP/Chapter3/signal.scm") 3 | 4 | (define (inverter input output) 5 | (define (invert-input) 6 | (let ((new-value 7 | (logical-not (get-signal input)))) 8 | (set-signal! output new-value))) 9 | (add-action! input invert-input) 10 | 'ok) 11 | 12 | (define (logical-not s) 13 | (cond ((= s 0) 1) 14 | ((= s 1) 0) 15 | (else (error "Invalid signal" s)))) 16 | 17 | (define (or-gate a1 a2 output) 18 | (define (or-action-procedure) 19 | (let ((new-value 20 | (logical-or (get-signal a1) 21 | (get-signal a2)))) 22 | (set-signal! output new-value))) 23 | (add-action! a1 or-action-procedure) 24 | (add-action! a2 or-action-procedure) 25 | 'ok) 26 | 27 | (define (logical-or a b) 28 | (if (or (= a 1) (= b 1)) 29 | 1 30 | 0)) 31 | 32 | (define a (make-wire)) 33 | (define b (make-wire)) 34 | (define c (make-wire)) 35 | 36 | ; (get-signal a) 37 | ; (get-signal b) 38 | ; (get-signal c) 39 | (or-gate a b c) 40 | (get-signal c) 41 | (set-signal! a 1) 42 | (get-signal c) 43 | (set-signal! b 1) 44 | (get-signal c) 45 | '3.28 46 | 47 | ; Welcome to DrRacket, version 6.7 [3m]. 48 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 49 | ; 'ok 50 | ; 0 51 | ; 'done 52 | ; 1 53 | ; 'done 54 | ; 1 55 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.29.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.29: Another way to construct an or-gate is as a compound digital logic device, built from and-gates and inverters. Define a procedure or-gate that accomplishes this. What is the delay time of the or-gate in terms of and-gate-delay and inverter-delay? 2 | (load "/home/soulomoon/git/SICP/Chapter3/signal.scm") 3 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.28.scm") 4 | (define (and-gate a1 a2 output) 5 | (define (and-action-procedure) 6 | (let ((new-value 7 | (logical-and (get-signal a1) 8 | (get-signal a2)))) 9 | (set-signal! output new-value))) 10 | (add-action! a1 and-action-procedure) 11 | (add-action! a2 and-action-procedure) 12 | 'ok) 13 | 14 | (define (logical-and a b) 15 | (if (and (= a 1) (= b 1)) 16 | 1 17 | 0)) 18 | 19 | (define (or-gate a1 a2 output) 20 | (let ((ow1 (make-wire)) 21 | (ow2 (make-wire)) 22 | (out (make-wire))) 23 | (inverter a1 ow1) 24 | (inverter a2 ow2) 25 | (and-gate ow1 ow2 out) 26 | (inverter out output))) 27 | 28 | (define a (make-wire)) 29 | (define b (make-wire)) 30 | (define c (make-wire)) 31 | 32 | ; (get-signal a) 33 | ; (get-signal b) 34 | ; (get-signal c) 35 | (or-gate a b c) 36 | (get-signal c) 37 | (set-signal! a 1) 38 | (get-signal c) 39 | (set-signal! b 1) 40 | (get-signal c) 41 | '3.29 42 | 43 | ; Welcome to DrRacket, version 6.7 [3m]. 44 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 45 | ; 'ok 46 | ; 0 47 | ; 'done 48 | ; 1 49 | ; 'done 50 | ; 1 51 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.31.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.31: The internal procedure accept-action-procedure! defined in make-wire specifies that when a new action procedure is added to a wire, the procedure is immediately run. Explain why this initialization is necessary. In particular, trace through the half-adder example in the paragraphs above and say how the system’s response would differ if we had defined accept-action-procedure! as 2 | 3 | (define (accept-action-procedure! proc) 4 | (set! action-procedures 5 | (cons proc action-procedures))) 6 | 7 | (define (make-wire) 8 | (let ((signal-value 0) 9 | (action-procedures '())) 10 | (define (set-my-signal! new-value) 11 | (if (not (= signal-value new-value)) 12 | (begin (set! signal-value new-value) 13 | (call-each 14 | action-procedures)) 15 | 'done)) 16 | (define (accept-action-procedure! proc) 17 | (set! action-procedures 18 | (cons proc action-procedures)) 19 | (proc)) 20 | (define (dispatch m) 21 | (cond ((eq? m 'get-signal) 22 | signal-value) 23 | ((eq? m 'set-signal!) 24 | set-my-signal!) 25 | ((eq? m 'add-action!) 26 | accept-action-procedure!) 27 | (else (error "Unknown operation: 28 | WIRE" m)))) 29 | dispatch)) 30 | 31 | 32 | ;if not being run immediately, then the change effect to a wire won't appear until that particular wire being set to a new signal -------------------------------------------------------------------------------- /Chapter3/Exercise3.32.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.32: The procedures to be run during each time segment of the agenda are kept in a queue. Thus, the procedures for each segment are called in the order in which they were added to the agenda (first in, first out). Explain why this order must be used. In particular, trace the behavior of an and-gate whose inputs change from 0, 1 to 1, 0 in the same segment and say how the behavior would differ if we stored a segment’s procedures in an ordinary list, adding and removing procedures only at the front (last in, first out). 2 | 3 | ; there are two ways for 0,1 to 1,0 4 | ; 0,1 -> 1,1 -> 1, 0 5 | ; 0,1 -> 0,0 -> 1, 0 6 | ; for which the queue, is the opposite of the order list 7 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.33.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.33: Using primitive multiplier, adder, and constant constraints, define a procedure averager that takes three connectors a, b, and c as inputs and establishes the constraint that the value of c is the average of the values of a and b. 2 | 3 | (load "/home/soulomoon/git/SICP/Chapter3/constraint.scm") 4 | (define (averager a b c) 5 | (let ((sum (make-connector)) 6 | (const (make-connector))) 7 | (constant 2 const) 8 | (adder a b sum) 9 | (multiplier const c sum))) 10 | 11 | (define a (make-connector)) 12 | (define b (make-connector)) 13 | (define c (make-connector)) 14 | 15 | (probe 'a a) 16 | (probe 'b b) 17 | (probe 'c c) 18 | 19 | (averager a b c) 20 | 21 | (set-value! a 1 'user) 22 | (set-value! b 10 'user) 23 | (forget-value! a 'user) 24 | (forget-value! a 'user) 25 | (set-value! c 22 'user) 26 | 27 | (get-value c) 28 | 29 | 30 | ; Welcome to DrRacket, version 6.7 [3m]. 31 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 32 | ; # 33 | ; # 34 | ; # 35 | ; # 36 | 37 | ; Probe: a = 1'done 38 | 39 | ; Probe: c = 11/2 40 | ; Probe: b = 10'done 41 | 42 | ; Probe: c = ? 43 | ; Probe: a = ?'done 44 | 45 | ; Probe: a = 34 46 | ; Probe: c = 22'done 47 | ; 22 48 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.34.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.34: Louis Reasoner wants to build a squarer, a constraint device with two terminals such that the value of connector b on the second terminal will always be the square of the value a on the first terminal. He proposes the following simple device made from a multiplier: 2 | 3 | ; (define (squarer a b) (multiplier a a b)) 4 | ; There is a serious flaw in this idea. Explain. 5 | (load "/home/soulomoon/git/SICP/Chapter3/constraint.scm") 6 | 7 | (define (squarer a b) (multiplier a a b)) 8 | 9 | (define a (make-connector)) 10 | (probe 'a a) 11 | (define b (make-connector)) 12 | (probe 'b b) 13 | 14 | (squarer a b) 15 | (set-value! a 1 'user) 16 | (forget-value! a 'user) 17 | (set-value! b 10 'user) 18 | 19 | ; Probe: a = 1 20 | ; Probe: b = 1'done 21 | 22 | ; Probe: a = ? 23 | ; Probe: b = ?'done 24 | 25 | ; Probe: b = 10'done 26 | ; > 27 | 28 | ; as we can see, if you try to set the second moniter's value, the first do not have enough imformation to get a root. that you have to impletment a single x in the constraint expression. -------------------------------------------------------------------------------- /Chapter3/Exercise3.36.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.36: Suppose we evaluate the following sequence of expressions in the global environment: 2 | 3 | ; (define a (make-connector)) 4 | ; (define b (make-connector)) 5 | ; (set-value! a 10 'user) 6 | ; At some time during evaluation of the set-value!, the following expression from the connector’s local procedure is evaluated: 7 | 8 | ; (for-each-except 9 | ; setter inform-about-value constraints) 10 | ; Draw an environment diagram showing the environment in which the above expression is evaluated. 11 | +-----------+ 12 | --| | 13 | +-----------+ 14 | ^ 15 | | 16 | +-----------------------------+<------+ 17 | |loop------------------------------->[*] [*]----> parameters:list 18 | |exception:'user | body:.... 19 | |procedure:inform-about-value | 20 | |list:'() | 21 | | | 22 | +-----------------------------+ 23 | ^ 24 | | 25 | +-----------+ 26 | |items:'() | 27 | +-----------+ 28 | (cond ((null? '() ) 'done) 29 | ((eq? (car '()) 'user) 30 | (loop (cdr '()))) 31 | (else (procedure (car '() )) 32 | (loop (cdr '() )))) 33 | 34 | (define (outside value) (+ value x)) 35 | (define x 1) 36 | (define (runner) 37 | (define x 2) 38 | (outside 1)) 39 | (define (runner1) 40 | (define x 2) 41 | (outside x)) 42 | 43 | ; Welcome to DrRacket, version 6.7 [3m]. 44 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 45 | ; > (runner) 46 | ; 2 47 | ; > (runner1) 48 | ; 3 49 | ; > 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.38.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.38: Suppose that Peter, Paul, and Mary share a joint bank account that initially contains $100. Concurrently, Peter deposits $10, Paul withdraws $20, and Mary withdraws half the money in the account, by executing the following commands: 2 | 3 | ; Peter: (set! balance (+ balance 10)) 4 | ; Paul: (set! balance (- balance 20)) 5 | ; Mary: (set! balance (- balance 6 | ; (/ balance 2))) 7 | ; List all the different possible values for balance after these three transactions have been completed, assuming that the banking system forces the three processes to run sequentially in some order. 8 | ; What are some other values that could be produced if the system allows the processes to be interleaved? Draw timing diagrams like the one in Figure 3.29 to explain how these values can occur. 9 | 10 | ;1: 4 results 40 45 50 35 11 | ; 2: one possible is that peter set! would be neglected quite like as Figure 3.29 -------------------------------------------------------------------------------- /Chapter3/Exercise3.39.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.39: Which of the five possibilities in the parallel execution shown above remain if we instead serialize execution as follows: 2 | 3 | ; (define x 10) 4 | ; (define s (make-serializer)) 5 | ; (parallel-execute 6 | ; (lambda () 7 | ; (set! x ((s (lambda () (* x x)))))) 8 | ; (s (lambda () (set! x (+ x 1))))) 9 | 10 | ;101 121 100 -------------------------------------------------------------------------------- /Chapter3/Exercise3.40.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.40: Give all possible values of x that can result from executing 2 | 3 | ; (define x 10) 4 | ; (parallel-execute 5 | ; (lambda () (set! x (* x x))) 6 | ; (lambda () (set! x (* x x x)))) 7 | ; Which of these possibilities remain if we instead use serialized procedures: 8 | 9 | ; (define x 10) 10 | ; (define s (make-serializer)) 11 | ; (parallel-execute 12 | ; (s (lambda () (set! x (* x x)))) 13 | ; (s (lambda () (set! x (* x x x))))) 14 | 15 | ; 1000000 -------------------------------------------------------------------------------- /Chapter3/Exercise3.41.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.41: Ben Bitdiddle worries that it would be better to implement the bank account as follows (where the commented line has been changed): 2 | 3 | ; (define (make-account balance) 4 | ; (define (withdraw amount) 5 | ; (if (>= balance amount) 6 | ; (begin 7 | ; (set! balance 8 | ; (- balance amount)) 9 | ; balance) 10 | ; "Insufficient funds")) 11 | ; (define (deposit amount) 12 | ; (set! balance (+ balance amount)) 13 | ; balance) 14 | ; (let ((protected (make-serializer))) 15 | ; (define (dispatch m) 16 | ; (cond ((eq? m 'withdraw) 17 | ; (protected withdraw)) 18 | ; ((eq? m 'deposit) 19 | ; (protected deposit)) 20 | ; ((eq? m 'balance) 21 | ; ((protected 22 | ; (lambda () 23 | ; balance)))) ; serialized 24 | ; (else 25 | ; (error 26 | ; "Unknown request: 27 | ; MAKE-ACCOUNT" 28 | ; m)))) 29 | ; dispatch)) 30 | ; because allowing unserialized access to the bank balance can result in anomalous behavior. Do you agree? Is there any scenario that demonstrates Ben’s concern? 31 | 32 | ; when depositing , and the proceess have not finished, the bank money would show to be the same while the cash money have been given to the mtn -------------------------------------------------------------------------------- /Chapter3/Exercise3.42.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.42: Ben Bitdiddle suggests that it’s a waste of time to create a new serialized procedure in response to every withdraw and deposit message. He says that make-account could be changed so that the calls to protected are done outside the dispatch procedure. That is, an account would return the same serialized procedure (which was created at the same time as the account) each time it is asked for a withdrawal procedure. 2 | 3 | ; (define (make-account balance) 4 | ; (define (withdraw amount) 5 | ; (if (>= balance amount) 6 | ; (begin (set! balance 7 | ; (- balance amount)) 8 | ; balance) 9 | ; "Insufficient funds")) 10 | ; (define (deposit amount) 11 | ; (set! balance (+ balance amount)) 12 | ; balance) 13 | ; (let ((protected (make-serializer))) 14 | ; (let ((protected-withdraw 15 | ; (protected withdraw)) 16 | ; (protected-deposit 17 | ; (protected deposit))) 18 | ; (define (dispatch m) 19 | ; (cond ((eq? m 'withdraw) 20 | ; protected-withdraw) 21 | ; ((eq? m 'deposit) 22 | ; protected-deposit) 23 | ; ((eq? m 'balance) 24 | ; balance) 25 | ; (else 26 | ; (error "Unknown request: 27 | ; MAKE-ACCOUNT" 28 | ; m)))) 29 | ; dispatch))) 30 | ; Is this a safe change to make? In particular, is there any difference in what concurrency is allowed by these two versions of make-account? 31 | 32 | ; it makes it run faster, and result is the same as before -------------------------------------------------------------------------------- /Chapter3/Exercise3.43.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.43: Suppose that the balances in three accounts start out as $10, $20, and $30, and that multiple processes run, exchanging the balances in the accounts. Argue that if the processes are run sequentially, after any number of concurrent exchanges, the account balances should be $10, $20, and $30 in some order. Draw a timing diagram like the one in Figure 3.29 to show how this condition can be violated if the exchanges are implemented using the first version of the account-exchange program in this section. On the other hand, argue that even with this exchange program, the sum of the balances in the accounts will be preserved. Draw a timing diagram to show how even this condition would be violated if we did not serialize the transactions on individual accounts. 2 | 3 | ; 20 --10--> 10 = 20 4 | ; 10 = 20 (right) 5 | ; the wrong begins 6 | ; 30 --20--> 10 = 40 7 | ; 20 = 10 8 | ; 30 = 10(should be 20) 9 | ; 10 = 40(should be 30) 10 | 11 | ; because of the lock on privete account, the total balance would be hold 12 | ; for every deposite on one account, there is a oppisite withdraw on the other account 13 | 14 | 15 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.44.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.44: Consider the problem of transferring an amount from one account to another. Ben Bitdiddle claims that this can be accomplished with the following procedure, even if there are multiple people concurrently transferring money among multiple accounts, using any account mechanism that serializes deposit and withdrawal transactions, for example, the version of make-account in the text above. 2 | 3 | ; (define 4 | ; (transfer from-account to-account amount) 5 | ; ((from-account 'withdraw) amount) 6 | ; ((to-account 'deposit) amount)) 7 | ; Louis Reasoner claims that there is a problem here, and that we need to use a more sophisticated method, such as the one required for dealing with the exchange problem. Is Louis right? If not, what is the essential difference between the transfer problem and the exchange problem? (You should assume that the balance in from-account is at least amount.) 8 | 9 | 10 | ; but it would always compute the right number opposite to exchange. 11 | ; the previous one have to compute the difference, the in that time gap, 12 | ; would getting a wrong blance 13 | ; transfer don't need this -------------------------------------------------------------------------------- /Chapter3/Exercise3.45.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.45: Louis Reasoner thinks our bank-account system is unnecessarily complex and error-prone now that deposits and withdrawals aren’t automatically serialized. He suggests that make-account-and-serializer should have exported the serializer (for use by such procedures as serialized-exchange) in addition to (rather than instead of) using it to serialize accounts and deposits as make-account did. He proposes to redefine accounts as follows: 2 | 3 | ; (define 4 | ; (make-account-and-serializer balance) 5 | ; (define (withdraw amount) 6 | ; (if (>= balance amount) 7 | ; (begin (set! balance 8 | ; (- balance amount)) 9 | ; balance) 10 | ; "Insufficient funds")) 11 | ; (define (deposit amount) 12 | ; (set! balance (+ balance amount)) 13 | ; balance) 14 | ; (let ((balance-serializer 15 | ; (make-serializer))) 16 | ; (define (dispatch m) 17 | ; (cond ((eq? m 'withdraw) 18 | ; (balance-serializer withdraw)) 19 | ; ((eq? m 'deposit) 20 | ; (balance-serializer deposit)) 21 | ; ((eq? m 'balance) 22 | ; balance) 23 | ; ((eq? m 'serializer) 24 | ; balance-serializer) 25 | ; (else (error "Unknown request: 26 | ; MAKE-ACCOUNT" 27 | ; m)))) 28 | ; dispatch)) 29 | ; Then deposits are handled as with the original make-account: 30 | 31 | ; (define (deposit account amount) 32 | ; ((account 'deposit) amount)) 33 | ; Explain what is wrong with Louis’s reasoning. In particular, consider what happens when serialized-exchange is called. 34 | 35 | ; double serialized, then dead lock -------------------------------------------------------------------------------- /Chapter3/Exercise3.46.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.46: Suppose that we implement test-and-set! using an ordinary procedure as shown in the text, without attempting to make the operation atomic. Draw a timing diagram like the one in Figure 3.29 to demonstrate how the mutex implementation can fail by allowing two processes to acquire the mutex at the same time. 2 | 3 | ; test1: false and test2:false, and it fails -------------------------------------------------------------------------------- /Chapter3/Exercise3.49.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.49: Give a scenario where the deadlock-avoidance mechanism described above does not work. (Hint: In the exchange problem, each process knows in advance which accounts it will need to get access to. Consider a situation where a process must get access to some shared resources before it can know which additional shared resources it will require.) 2 | 3 | ; if you have to require the first lock, and not sure about the other lock 4 | ; suppose you need to open a door from and get in the room the see what is the other door number, and you have to get the key in the same place. and the other on open the second door which you suppose to open after, and then need to open your door, so you went to take the your key, and found out the other door number, in the mean time the other person do the same, and you both end up tring to get other's key -------------------------------------------------------------------------------- /Chapter3/Exercise3.50.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.50: Complete the following definition, which generalizes stream-map to allow procedures that take multiple arguments, analogous to map in 2.2.1, Footnote 78. 2 | 3 | ; (define (stream-map proc . argstreams) 4 | ; (if (⟨??⟩ (car argstreams)) 5 | ; the-empty-stream 6 | ; (⟨??⟩ 7 | ; (apply proc (map ⟨??⟩ argstreams)) 8 | ; (apply stream-map 9 | ; (cons proc 10 | ; (map ⟨??⟩ 11 | ; argstreams)))))) 12 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 13 | 14 | (define (stream-map proc . argstreams) 15 | (if (stream-null? (car argstreams)) 16 | the-empty-stream 17 | (cons-stream 18 | (apply proc (map stream-car argstreams)) 19 | (apply stream-map 20 | (cons proc 21 | (map stream-cdr 22 | argstreams)))))) 23 | 24 | (define a (stream-enumerate-interval 10 20)) 25 | (define b (stream-enumerate-interval 10 20)) 26 | 27 | (define c (stream-map + a b a)) 28 | 29 | (display-stream c) 30 | 31 | ; Welcome to DrRacket, version 6.7 [3m]. 32 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 33 | 34 | ; 30 35 | ; 33 36 | ; 36 37 | ; 39 38 | ; 42 39 | ; 45 40 | ; 48 41 | ; 51 42 | ; 54 43 | ; 57 44 | ; 60'done 45 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.51.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.51: In order to take a closer look at delayed evaluation, we will use the following procedure, which simply returns its argument after printing it: 2 | 3 | ; (define (show x) 4 | ; (display-line x) 5 | ; x) 6 | ; What does the interpreter print in response to evaluating each expression in the following sequence?187 7 | 8 | ; (define x 9 | ; (stream-map 10 | ; show 11 | ; (stream-enumerate-interval 0 10))) 12 | 13 | ; (stream-ref x 5) 14 | ; (stream-ref x 7) 15 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 16 | 17 | (define (show x) 18 | (display-line x) 19 | x) 20 | 21 | (define x 22 | (stream-map 23 | show 24 | (stream-enumerate-interval 0 10))) 25 | 26 | (stream-ref x 5) 27 | (stream-ref x 7) 28 | (stream-ref x 4) 29 | 30 | 31 | ; Welcome to DrRacket, version 6.7 [3m]. 32 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 33 | 34 | ; 0 35 | ; 1 36 | ; 2 37 | ; 3 38 | ; 4 39 | ; 55 40 | 41 | ; 6 42 | ; 77 43 | ; 4 44 | ; > 45 | 46 | 47 | ;it runs it to get what it need when it need it, and cach it in memory. -------------------------------------------------------------------------------- /Chapter3/Exercise3.52.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.52: Consider the sequence of expressions 2 | 3 | ; (define sum 0) 4 | 5 | ; (define (accum x) 6 | ; (set! sum (+ x sum)) 7 | ; sum) 8 | 9 | ; (define seq 10 | ; (stream-map 11 | ; accum 12 | ; (stream-enumerate-interval 1 20))) 13 | 14 | ; (define y (stream-filter even? seq)) 15 | 16 | ; (define z 17 | ; (stream-filter 18 | ; (lambda (x) 19 | ; (= (remainder x 5) 0)) seq)) 20 | 21 | ; (stream-ref y 7) 22 | ; (display-stream z) 23 | ; What is the value of sum after each of the above expressions is evaluated? What is the printed response to evaluating the stream-ref and display-stream expressions? Would these responses differ if we had implemented (delay ⟨exp⟩) simply as (lambda () ⟨exp⟩) without using the optimization provided by memo-proc? Explain. 24 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 25 | (define sum 0) 26 | 27 | (define (accum x) 28 | (set! sum (+ x sum)) 29 | sum) 30 | ; 0 31 | 32 | (define seq 33 | (stream-map 34 | accum 35 | (stream-enumerate-interval 1 20))) 36 | 37 | ; 1 38 | 39 | 40 | (define y (stream-filter even? seq)) 41 | 42 | ; 6 43 | 44 | (define z 45 | (stream-filter 46 | (lambda (x) 47 | (= (remainder x 5) 0)) seq)) 48 | ; 10 49 | 50 | (stream-ref y 7) 51 | ; 136 52 | (display-stream z) 53 | ; 210 54 | 55 | ; if without memo-proc, the accum would not be the same, so if trying to use accum more, the result would increase with each time you use it. 56 | 57 | 58 | ; Welcome to DrRacket, version 6.7 [3m]. 59 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 60 | ; 136 61 | 62 | ; 10 63 | ; 15 64 | ; 45 65 | ; 55 66 | ; 105 67 | ; 120 68 | ; 190 69 | ; 210'done 70 | ; > 71 | 72 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.53.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.53: Without running the program, describe the elements of the stream defined by 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | (define (add-streams s1 s2) 4 | (stream-map + s1 s2)) 5 | ; (define s (cons-stream 1 (add-streams s s))) 6 | (define s (cons-stream 1 (add-streams s s))) 7 | ; 1 2 4 8 16 just as 8 | ; (define double 9 | ; (cons-stream 1 (scale-stream double 2))) 10 | 11 | (stream-ref s 10) 12 | 13 | 14 | ; Welcome to DrRacket, version 6.7 [3m]. 15 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 16 | ; 1024 17 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.54.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.54: Define a procedure mul-streams, analogous to add-streams, that produces the elementwise product of its two input streams. Use this together with the stream of integers to complete the following definition of the stream whose nthnth element (counting from 0) is n+1n+1 factorial: 2 | 3 | ; (define factorials 4 | ; (cons-stream 1 (mul-streams ⟨??⟩ ⟨??⟩))) 5 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 6 | (define (add-streams s1 s2) 7 | (stream-map + s1 s2)) 8 | (define (mul-streams s1 s2) 9 | (stream-map * s1 s2)) 10 | (define ones (cons-stream 1 ones)) 11 | (define integers 12 | (cons-stream 1 (add-streams ones integers))) 13 | 14 | (define factorials 15 | (cons-stream 1 (mul-streams integers factorials))) 16 | 17 | (define a 18 | (stream-map (lambda (n) 19 | (stream-ref factorials n)) (stream-enumerate-interval 0 20))) 20 | 21 | (display-stream a) 22 | ; Welcome to DrRacket, version 6.7 [3m]. 23 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 24 | 25 | ; 1 26 | ; 1 27 | ; 2 28 | ; 6 29 | ; 24 30 | ; 120 31 | ; 720 32 | ; 5040 33 | ; 40320 34 | ; 362880 35 | ; 3628800 36 | ; 39916800 37 | ; 479001600 38 | ; 6227020800 39 | ; 87178291200 40 | ; 1307674368000 41 | ; 20922789888000 42 | ; 355687428096000 43 | ; 6402373705728000 44 | ; 121645100408832000 45 | ; 2432902008176640000'done 46 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.55.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.55: Define a procedure partial-sums that takes as argument a stream SS and returns the stream whose elements are S0S0, S0+S1S0+S1, S0+S1+S2,…S0+S1+S2,…. For example, (partial-sums integers) should be the stream 1, 3, 6, 10, 15, …. 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | 4 | 5 | (define (partial-sums s) 6 | (cons-stream (stream-car s) (add-streams (partial-sums s) (stream-cdr s)))) 7 | 8 | (define b (partial-sums integers)) 9 | 10 | (define a 11 | (stream-map (lambda (n) 12 | (stream-ref b n)) (stream-enumerate-interval 0 20))) 13 | 14 | (display-stream a) 15 | 16 | 17 | ; Welcome to DrRacket, version 6.7 [3m]. 18 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 19 | 20 | ; 1 21 | ; 3 22 | ; 6 23 | ; 10 24 | ; 15 25 | ; 21 26 | ; 28 27 | ; 36 28 | ; 45 29 | ; 55 30 | ; 66 31 | ; 78 32 | ; 91 33 | ; 105 34 | ; 120 35 | ; 136 36 | ; 153 37 | ; 171 38 | ; 190 39 | ; 210 40 | ; 231'done 41 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.57.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.57: How many additions are performed when we compute the nthnth Fibonacci number using the definition of fibs based on the add-streams procedure? Show that the number of additions would be exponentially greater if we had implemented (delay ⟨exp⟩) simply as (lambda () ⟨exp⟩), without using the optimization provided by the memo-proc procedure described in 3.5.1.192 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | 4 | (define counter 0) 5 | 6 | (define (+withcounter s1 s2) 7 | (set! counter (+ counter 1)) 8 | (+ s1 s2)) 9 | 10 | (define (add-streams s1 s2) 11 | (stream-map +withcounter s1 s2)) 12 | 13 | (define fibs 14 | (cons-stream 15 | 0 (cons-stream 16 | 1 (add-streams 17 | (stream-cdr fibs) fibs)))) 18 | 19 | (newline )(stream-ref fibs 20) 20 | (newline )(display counter)(newline ) 21 | 22 | ; 19 times, it would be o(n) 23 | ; if not remember each time it accessed a fibs, 24 | ; supose it is n, then you have to access n-1 and n-2, make each step you take in to fib would be near twice the time you need for previous then the total time would be o(2^n) 25 | ; remembering means that it would eleminate the eatra n-2 part,each time, then you only need o(n) time,and it also take o(n) space to storage. 26 | 27 | ; Welcome to DrRacket, version 6.7 [3m]. 28 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 29 | 30 | ; 6765 31 | 32 | ; 19 33 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.58.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.58: Give an interpretation of the stream computed by the following procedure: 2 | 3 | ; (define (expand num den radix) 4 | ; (cons-stream 5 | ; (quotient (* num radix) den) 6 | ; (expand (remainder (* num radix) den) 7 | ; den 8 | ; radix))) 9 | ; (Quotient is a primitive that returns the integer quotient of two integers.) What are the successive elements produced by (expand 1 7 10)? What is produced by (expand 3 8 10)? 10 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 11 | 12 | (define (expand num den radix) 13 | (cons-stream 14 | (quotient (* num radix) den) 15 | (expand (remainder (* num radix) den) 16 | den 17 | radix))) 18 | 19 | 20 | (display-stream 21 | (stream-map 22 | (lambda (n) 23 | (stream-ref (expand 1 7 10) n)) (stream-enumerate-interval 0 20))) 24 | ; 1 7 10 25 | ; ~1 26 | ; 3 7 10 27 | ; ~4 28 | ; 2 7 10 29 | ; ~2 30 | ; 6 7 10 31 | ; ~8 32 | 33 | (display-stream 34 | (stream-map 35 | (lambda (n) 36 | (stream-ref (expand 3 8 10) n)) (stream-enumerate-interval 0 20))) 37 | ; 3 8 10 38 | ; ~3 39 | ; 6 8 10 40 | ; ~7 41 | ; 4 8 10 42 | ; ~5 43 | ; 0 8 10 44 | ; ~0 45 | ; 0 8 10 46 | ; ~0 -------------------------------------------------------------------------------- /Chapter3/Exercise3.60.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.60: With power series represented as streams of coefficients as in Exercise 3.59, adding series is implemented by add-streams. Complete the definition of the following procedure for multiplying series: 2 | 3 | ; (define (mul-series s1 s2) 4 | ; (cons-stream ⟨??⟩ (add-streams ⟨??⟩ ⟨??⟩))) 5 | ; You can test your procedure by verifying that sin2x+cos2x=1,sin2⁡x+cos2⁡x=1, using the series from Exercise 3.59. 6 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.59.scm") 7 | 8 | 9 | (define (mul-series s1 s2) 10 | (cons-stream (* (stream-car s1) (stream-car s2)) 11 | (add-streams (add-streams (mul-series (stream-cdr s1) s2) 12 | (mul-series s1 (stream-cdr s2))) 13 | (scale-stream 14 | (cons-stream 0 (mul-series (stream-cdr s1) (stream-cdr s2))) 15 | -1)))) 16 | 17 | ; (define s (mul-series ones ones)) 18 | 19 | (define s (add-streams (mul-series cosine-series cosine-series) 20 | (mul-series sine-series sine-series))) 21 | 22 | ; (display-stream 23 | ; (stream-map (lambda (n) 24 | ; (stream-ref s n)) 25 | ; (stream-enumerate-interval 0 10))) 26 | 27 | ; Welcome to DrRacket, version 6.7 [3m]. 28 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 29 | 30 | ; 1 31 | ; 0 32 | ; 0 33 | ; 0 34 | ; 0 35 | ; 0 36 | ; 0 37 | ; 0 38 | ; 0 39 | ; 0 40 | ; 0'done 41 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.61.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.61: Let SS be a power series (Exercise 3.59) whose constant term is 1. Suppose we want to find the power series 1/S1/S, that is, the series XX such that SX=1SX=1. Write S=1+SRS=1+SR where SRSR is the part of SS after the constant term. Then we can solve for XX as follows: 2 | ; S⋅X(1+SR)⋅XX+SR⋅XX====1,1,1,1−SR⋅X. 3 | ; S⋅X=1,(1+SR)⋅X=1,X+SR⋅X=1,X=1−SR⋅X. 4 | ; In other words, XX is the power series whose constant term is 1 and whose higher-order terms are given by the negative of SRSR times XX. Use this idea to write a procedure invert-unit-series that computes 1/S1/S for a power series SS with constant term 1. You will need to use mul-series from Exercise 3.60. 5 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.60.scm") 6 | 7 | (define (invert-unit-series S) 8 | (let ((Sr (stream-cdr S))) 9 | (define X 10 | (cons-stream 11 | 1 12 | (scale-stream 13 | (mul-series Sr X) 14 | -1))) 15 | X)) 16 | 17 | (define nones (invert-unit-series ones)) 18 | (define s (mul-series nones ones)) 19 | 20 | ; (display-stream 21 | ; (stream-map (lambda (n) 22 | ; (stream-ref s n)) 23 | ; (stream-enumerate-interval 0 10))) 24 | 25 | 26 | ; Welcome to DrRacket, version 6.7 [3m]. 27 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 28 | 29 | ; 1 30 | ; 0 31 | ; 0 32 | ; 0 33 | ; 0 34 | ; 0 35 | ; 0 36 | ; 0 37 | ; 0 38 | ; 0 39 | ; 0'done 40 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.62.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.62: Use the results of Exercise 3.60 and Exercise 3.61 to define a procedure div-series that divides two power series. Div-series should work for any two series, provided that the denominator series begins with a nonzero constant term. (If the denominator has a zero constant term, then div-series should signal an error.) Show how to use div-series together with the result of Exercise 3.59 to generate the power series for tangent. 2 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.61.scm") 3 | 4 | (define (div-series a b) 5 | (if (= (stream-car b) 0) 6 | (error "0 constant in denominator") 7 | (mul-series a (invert-unit-series b)))) 8 | 9 | 10 | (define s (div-series ones ones)) 11 | 12 | 13 | (display-stream 14 | (stream-map (lambda (n) 15 | (stream-ref s n)) 16 | (stream-enumerate-interval 0 10))) 17 | 18 | ; Welcome to DrRacket, version 6.7 [3m]. 19 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 20 | 21 | ; 1 22 | ; 0 23 | ; 0 24 | ; 0 25 | ; 0 26 | ; 0 27 | ; 0 28 | ; 0 29 | ; 0 30 | ; 0 31 | ; 0'done 32 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.63.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.63: Louis Reasoner asks why the sqrt-stream procedure was not written in the following more straightforward way, without the local variable guesses: 2 | 3 | ; (define (sqrt-stream x) 4 | ; (cons-stream 5 | ; 1.0 6 | ; (stream-map (lambda (guess) 7 | ; (sqrt-improve guess x)) 8 | ; (sqrt-stream x)))) 9 | ; Alyssa P. Hacker replies that this version of the procedure is considerably less efficient because it performs redundant computation. Explain Alyssa’s answer. Would the two versions still differ in efficiency if our implementation of delay used only (lambda () ⟨exp⟩) without using the optimization provided by memo-proc (3.5.1)? 10 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.62.scm") 11 | 12 | (define (sqrt-stream x) 13 | (define guesses 14 | (cons-stream 15 | 1.0 (stream-map 16 | (lambda (guess) 17 | (sqrt-improve guess x)) 18 | guesses))) 19 | guesses) 20 | 21 | (define (sqrt-stream x) 22 | (cons-stream 23 | 1.0 24 | (stream-map (lambda (guess) 25 | (sqrt-improve guess x)) 26 | (sqrt-stream x)))) 27 | 28 | ; if define the guess it would run in the same guess, memo-proc enable it to store the already runned value inside delayed object, help it run faster, 29 | ; be if using louisreasoner's version, it every stream-map would callout a different (sqrt-stream), thus, the memo-proc is not working. 30 | ; when memo-proc, two should be the same -------------------------------------------------------------------------------- /Chapter3/Exercise3.64.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.64: Write a procedure stream-limit that takes as arguments a stream and a number (the tolerance). It should examine the stream until it finds two successive elements that differ in absolute value by less than the tolerance, and return the second of the two elements. Using this, we could compute square roots up to a given tolerance by 2 | 3 | ; (define (sqrt x tolerance) 4 | ; (stream-limit (sqrt-stream x) tolerance)) 5 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 6 | (define (average x y) 7 | (/ (+ x y) 2)) 8 | 9 | (define (stream-limit s tolerance) 10 | (let ((first-ele (stream-car s)) 11 | (second-ele (stream-car (stream-cdr s))) 12 | (rest-stream (stream-cdr s))) 13 | (let ((differ (abs (- first-ele second-ele)))) 14 | (if (< differ tolerance) 15 | second-ele 16 | (stream-limit rest-stream tolerance))))) 17 | 18 | (define (sqrt x tolerance) 19 | (stream-limit (sqrt-stream x) tolerance)) 20 | (define (sqrt-improve guess x) 21 | (average guess (/ x guess))) 22 | (define (sqrt-stream x) 23 | (define guesses 24 | (cons-stream 25 | 1.0 (stream-map 26 | (lambda (guess) 27 | (sqrt-improve guess x)) 28 | guesses))) 29 | guesses) 30 | 31 | (sqrt 2 0.00001) 32 | 33 | ; Welcome to DrRacket, version 6.7 [3m]. 34 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 35 | ; 1.4142135623746899 36 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.66.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.66: Examine the stream (pairs integers integers). Can you make any general comments about the order in which the pairs are placed into the stream? For example, approximately how many pairs precede the pair (1, 100)? the pair (99, 100)? the pair (100, 100)? (If you can make precise mathematical statements here, all the better. But feel free to give more qualitative answers if you find yourself getting bogged down.) 2 | 3 | (1, 100) preceding first there are (1, 1) to (1, 99) 4 | total 99, then observing the interleave, there would be 98 with form of (n, m), 5 | where n > 1, m < 99. 6 | total 197 7 | with total of m pick, 8 | approximately. 9 | 1/2:(1, n) 10 | 1/4:(2, n) 11 | 1/8:(3, n) 12 | 1/2^k:(k, n) 13 | because the first is (1, 1) 14 | and there are not coresponding (2, 1) 15 | then you have to count for (n, 1)'s location 16 | every time step into the next, you have to in pair stage take two step 17 | for nth pair one step means 2^(n-1) 18 | (1, 1): 1 19 | (2, 1): 2 * 1 + 1 20 | (3, 1): 2 * 2 + 2 * 1 + 1 21 | (n ,1): 2^n - 1 22 | 23 | for (n, m)'location, take step too, 24 | you need two step to get to the next m, except for the second one , which you only need one step to get to 25 | (n, 2): 2^n - 1 + 2^(n-1) 26 | (n ,3): 2^n - 1 + 2^(n-1) +2^n 27 | (n, m): (m-1) * 2^n + 2^(n-1) -1 28 | 29 | conclude: 30 | (n, 1): 2^n -1 31 | (n, m): m * 2^n - 2^(n-1) -1 32 | 33 | 34 | so the total preceding pairs: 35 | for (1, 100): 100*2 - 2 - 1 = 197 36 | for (99, 100): 100*2^99 - 2^98 - 2 37 | for (100, 100):100*2^100 - 2^99 - 2 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Chapter3/Exercise3.67.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.67: Modify the pairs procedure so that (pairs integers integers) will produce the stream of all pairs of integers (i,j)(i,j) (without the condition i≤ji≤j). Hint: You will need to mix in an additional stream. 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | (define (interleave s1 s2) 4 | (if (stream-null? s1) 5 | s2 6 | (cons-stream 7 | (stream-car s1) 8 | (interleave s2 (stream-cdr s1))))) 9 | 10 | ; (define (pairs s t) 11 | ; (cons-stream 12 | ; (list (stream-car s) (stream-car t)) 13 | ; (interleave 14 | ; (stream-map (lambda (x) 15 | ; (list (stream-car s) x)) 16 | ; (stream-cdr t)) 17 | ; (pairs (stream-cdr s) (stream-cdr t))))) 18 | (define (pairs s t) 19 | (cons-stream 20 | (list (stream-car s) (stream-car t)) 21 | (interleave 22 | (interleave 23 | (stream-map (lambda (x) 24 | (list (stream-car s) x)) 25 | (stream-cdr t)) 26 | (stream-map (lambda (x) 27 | (list x (stream-car s))) 28 | (stream-cdr t))) 29 | (pairs (stream-cdr s) (stream-cdr t))))) 30 | 31 | (display-10 (pairs integers integers)) 32 | 33 | ; Welcome to DrRacket, version 6.7 [3m]. 34 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 35 | 36 | ; (1 1) 37 | ; (1 2) 38 | ; (2 2) 39 | ; (2 1) 40 | ; (2 3) 41 | ; (1 3) 42 | ; (3 3) 43 | ; (3 1) 44 | ; (3 2) 45 | ; (1 4)'done 46 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.68.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.68: Louis Reasoner thinks that building a stream of pairs from three parts is unnecessarily complicated. Instead of separating the pair (S0,T0)(S0,T0) from the rest of the pairs in the first row, he proposes to work with the whole first row, as follows: 2 | 3 | ; (define (pairs s t) 4 | ; (interleave 5 | ; (stream-map 6 | ; (lambda (x) 7 | ; (list (stream-car s) x)) 8 | ; t) 9 | ; (pairs (stream-cdr s) 10 | ; (stream-cdr t)))) 11 | ; Does this work? Consider what happens if we evaluate (pairs integers integers) using Louis’s definition of pairs. 12 | 13 | ; infinite evaluate the interleave and pairs -------------------------------------------------------------------------------- /Chapter3/Exercise3.69.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.69: Write a procedure triples that takes three infinite streams, SS, TT, and UU, and produces the stream of triples (Si,Tj,Uk)(Si,Tj,Uk) such that i≤j≤ki≤j≤k. Use triples to generate the stream of all Pythagorean triples of positive integers, i.e., the triples (i,j,k)(i,j,k) such that i≤ji≤j and i2+j2=k2i2+j2=k2. 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | (define (interleave s1 s2) 4 | (if (stream-null? s1) 5 | s2 6 | (cons-stream 7 | (stream-car s1) 8 | (interleave s2 (stream-cdr s1))))) 9 | 10 | (define (pairs s t) 11 | (cons-stream 12 | (list (stream-car s) (stream-car t)) 13 | (interleave 14 | (stream-map (lambda (x) 15 | (list (stream-car s) x)) 16 | (stream-cdr t)) 17 | (pairs (stream-cdr s) (stream-cdr t))))) 18 | 19 | (define (triples S T U) 20 | (cons-stream 21 | (map stream-car (list S T U)) 22 | (interleave 23 | (stream-map (lambda (x) 24 | (cons (stream-car S) x)) 25 | (pairs T (stream-cdr U))) 26 | (apply triples (map stream-cdr (list S T U)))))) 27 | 28 | (define (pythagorean_pre s) 29 | (let ((i (car s)) 30 | (j (cadr s)) 31 | (k (caddr s))) 32 | (if (= (+ (square i) (square j)) (square k)) 33 | true 34 | false))) 35 | (define Pythagorean 36 | (stream-filter pythagorean_pre (triples integers integers integers))) 37 | 38 | 39 | (display-10 Pythagorean) 40 | 41 | ; Welcome to DrRacket, version 6.7 [3m]. 42 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 43 | 44 | ; (3 4 5) 45 | ; (6 8 10) 46 | ; (5 12 13) 47 | ; (9 12 15) 48 | ; (8 15 17) 49 | ; (12 16 20) 50 | ; (15 20 25) -------------------------------------------------------------------------------- /Chapter3/Exercise3.71.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.71: Numbers that can be expressed as the sum of two cubes in more than one way are sometimes called Ramanujan numbers, in honor of the mathematician Srinivasa Ramanujan.198 Ordered streams of pairs provide an elegant solution to the problem of computing these numbers. To find a number that can be written as the sum of two cubes in two different ways, we need only generate the stream of pairs of integers (i,j)(i,j) weighted according to the sum i3+j3i3+j3 (see Exercise 3.70), then search the stream for two consecutive pairs with the same weight. Write a procedure to generate the Ramanujan numbers. The first such number is 1,729. What are the next five? 2 | 3 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.70.scm") 4 | 5 | (define (Ramanujan_weight pair) 6 | (+ (expt (car pair) 3) (expt (cadr pair) 3))) 7 | 8 | (define Ramanujan_weighted_stream (weighted-pairs integers integers Ramanujan_weight)) 9 | 10 | (define (Ramanujan_iter S) 11 | (let ((first (Ramanujan_weight (stream-car S))) 12 | (rest (stream-cdr S))) 13 | (let ((second (Ramanujan_weight (stream-car rest)))) 14 | (if (= first second) 15 | (cons-stream 16 | first 17 | (Ramanujan_iter rest)) 18 | (Ramanujan_iter rest))))) 19 | 20 | (define Ramanujan_numbers (Ramanujan_iter Ramanujan_weighted_stream)) 21 | 22 | ; (display-10 Ramanujan_numbers) 23 | 24 | ; Welcome to DrRacket, version 6.7 [3m]. 25 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 26 | 27 | ; 1729 28 | ; 4104 29 | ; 13832 30 | ; 20683 31 | ; 32832 32 | ; 39312 33 | ; 40033 34 | ; 46683 35 | ; 64232 36 | ; 65728 37 | ; 110656'done 38 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.72.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.72: In a similar way to Exercise 3.71 generate a stream of all numbers that can be written as the sum of two squares in three different ways (showing how they can be so written). 2 | (load "/home/soulomoon/git/SICP/Chapter3/Exercise3.71.scm") 3 | 4 | (define (three_Ramanujan_iter S) 5 | (let ((first (stream-car S)) 6 | (rest (stream-cdr S))) 7 | (let ((second (stream-car rest)) 8 | (third (stream-car (stream-cdr rest)))) 9 | (if (= (Ramanujan_weight first) 10 | (Ramanujan_weight second) 11 | (Ramanujan_weight third)) 12 | (cons-stream 13 | (list first second third (Ramanujan_weight first)) 14 | (three_Ramanujan_iter rest)) 15 | (three_Ramanujan_iter rest))))) 16 | 17 | (define three_Ramanujan_numbers 18 | (three_Ramanujan_iter Ramanujan_weighted_stream)) 19 | 20 | (display-10 three_Ramanujan_numbers) 21 | 22 | ; Welcome to DrRacket, version 6.7 [3m]. 23 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 24 | 25 | ; ((167 436) (228 423) (255 414) 87539319) 26 | ; ((11 493) (90 492) (346 428) 119824488) 27 | ; ((111 522) (359 460) (408 423) 143604279) 28 | ; ((70 560) (198 552) (315 525) 175959000). . user break 29 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.79.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.79: Generalize the solve-2nd procedure of Exercise 3.78 so that it can be used to solve general second-order differential equations d2y/dt2=f(dy/dt,y)d2y/dt2=f(dy/dt,y). 2 | 3 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 4 | 5 | (define (integral 6 | delayed-integrand initial-value dt) 7 | (define int 8 | (cons-stream 9 | initial-value 10 | (let ((integrand 11 | (force delayed-integrand))) 12 | (add-streams 13 | (scale-stream integrand dt) 14 | int)))) 15 | int) 16 | 17 | 18 | (define (solve dt y0 dy0) 19 | (define dy (delay (integral y dy0 dt))) 20 | (define y (delay (integral dy y0 dt))) 21 | (force y)) 22 | 23 | (define (solve-gnd f dt y0 dy0) 24 | (define dy (delay (integral ddy dy0 dt))) 25 | (define y (delay (integral dy y0 dt))) 26 | (define ddy 27 | (delay 28 | (scale-stream 29 | (stream-map 30 | f 31 | (scale-stream (force dy) (/ 1 dt)) 32 | (force y)) 33 | (square dt)))) 34 | (force y)) 35 | (define f 36 | (lambda (dy/dt y) 37 | (+ dy/dt y))) 38 | 39 | (stream-ref (solve 0.0001 1 1) 10000) 40 | (stream-ref (solve-gnd f 0.0001 1 1) 10000) 41 | 42 | ; Welcome to DrRacket, version 6.7 [3m]. 43 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 44 | ; 2.7181459268252266 45 | ; 2.0000500033321242 46 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.81.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.81: Exercise 3.6 discussed generalizing the random-number generator to allow one to reset the random-number sequence so as to produce repeatable sequences of “random” numbers. Produce a stream formulation of this same generator that operates on an input stream of requests to generate a new random number or to reset the sequence to a specified value and that produces the desired stream of random numbers. Don’t use assignment in your solution. 2 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 3 | 4 | 5 | (define (rand-update x) 6 | (let ((a 27) (b 26) (m 127)) 7 | (modulo (+ (* a x) b) m))) 8 | 9 | (define (rand op_stream) 10 | (define (next op_stream number) 11 | (cons-stream 12 | number 13 | (rand_inner op_stream number))) 14 | (define (rand_inner op_stream number) 15 | (let ((m (if (null? op_stream) '() (stream-car op_stream)))) 16 | (cond 17 | ((null? m) (next op_stream number)) 18 | ((eq? m 'reset) 19 | (next 20 | (stream-cdr (stream-cdr op_stream)) 21 | (stream-car (stream-cdr op_stream)))) 22 | ((eq? m 'generate) 23 | (next 24 | (stream-cdr op_stream) 25 | (rand-update number))) 26 | (else (error "unknow request" m))))) 27 | (rand_inner op_stream 10)) 28 | 29 | (define cmds 30 | (list_to_stream 31 | (list 32 | 'generate 33 | 'generate 34 | 'generate 35 | 'reset 36 | 99 37 | 'generate 38 | 'generate 39 | 'reset 40 | 66 41 | 'generate 42 | ))) 43 | 44 | (define a (rand cmds)) 45 | (display-10 a) 46 | 47 | 48 | ; Welcome to DrRacket, version 6.7 [3m]. 49 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 50 | ; 51 | ; 42 52 | ; 17 53 | ; 104 54 | ; 99 55 | ; 32 56 | ; 1 57 | ; 66 58 | ; 30 59 | ; 30 60 | ; 30 61 | ; 30'done 62 | ; > -------------------------------------------------------------------------------- /Chapter3/Exercise3.82.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 3.82: Redo Exercise 3.5 on Monte Carlo integration in terms of streams. The stream version of estimate-integral will not have an argument telling how many trials to perform. Instead, it will produce a stream of estimates based on successively more trials. 2 | 3 | (load "/home/soulomoon/git/SICP/Chapter3/stream.scm") 4 | 5 | 6 | (define (monte-carlo experiment-stream 7 | passed 8 | failed) 9 | (define (next passed failed) 10 | (cons-stream 11 | (/ passed (+ passed failed)) 12 | (monte-carlo 13 | (stream-cdr experiment-stream) 14 | passed 15 | failed))) 16 | (if (stream-car experiment-stream) 17 | (next (+ passed 1) failed) 18 | (next passed (+ failed 1)))) 19 | 20 | 21 | (define (random-in-range low high) 22 | (let ((range (- high low))) 23 | (+ low (random range)))) 24 | 25 | (define (random_stream low high) 26 | (cons-stream 27 | (random-in-range low high) 28 | (random_stream low high))) 29 | 30 | 31 | (define (round_test_stream x1 x2 y1 y2) 32 | (stream-map 33 | (lambda (x y) 34 | (<= 35 | (+ 36 | (square (- x (average x1 x2))) 37 | (square (- y (average y1 y2)))) 38 | (square (/ (- x2 x1) 2)))) 39 | (random_stream x1 x2) 40 | (random_stream y1 y2))) 41 | 42 | (define (estimate-integral x1 x2 y1 y2) 43 | (let ((es (round_test_stream x1 x2 y1 y2))) 44 | (stream-map 45 | (lambda (x) (* x 4)) 46 | (monte-carlo es 0 0)))) 47 | 48 | 49 | (define pi 50 | (estimate-integral 20 80 40 100)) 51 | 52 | (stream-ref pi 1) 53 | 54 | ; Welcome to DrRacket, version 6.7 [3m]. 55 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 56 | ; 3 13005/100001 57 | ; > 58 | 59 | -------------------------------------------------------------------------------- /Chapter3/parallel-execute.scm: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require sicp) 3 | (provide make-mutex) 4 | (provide test-and-set!) 5 | (provide make-serializer) 6 | (define (parallel-execute . procs) 7 | (map thread-wait 8 | (map (lambda (proc) (thread proc)) 9 | procs))) 10 | 11 | (define (make-serializer) 12 | (let ((mutex (make-mutex))) 13 | (lambda (p) 14 | (define (serialized-p . args) 15 | (mutex 'acquire) 16 | (let ((val (apply p args))) 17 | (mutex 'release) 18 | val)) 19 | serialized-p))) 20 | 21 | 22 | (define (make-mutex) 23 | (let ((cell (list false))) 24 | (define (the-mutex m) 25 | (cond ((eq? m 'acquire) 26 | (if (test-and-set! cell) 27 | (the-mutex 'acquire))) ; retry 28 | ((eq? m 'release) (clear! cell)))) 29 | the-mutex)) 30 | (define (clear! cell) (set-car! cell false)) 31 | 32 | 33 | (define (test-and-set! cell) 34 | (if (car cell) 35 | true 36 | (begin (set-car! cell true) 37 | false))) 38 | 39 | 40 | ; (define s (make-serializer)) 41 | ; (define (test x) (begin (parallel-execute (lambda () (set! x (+ x 1))) 42 | ; (lambda () (set! x (* x x)))) 43 | ; (display x)(newline))) 44 | 45 | ; (define (loop f n) 46 | ; (let ((x 10)) 47 | ; (if (= n 0) 48 | ; false 49 | ; (begin (set! n (- n 1)) (f x) (loop f n)) 50 | ; ) 51 | ; ) 52 | ; ) 53 | 54 | ; (loop test 100) -------------------------------------------------------------------------------- /Chapter3/queue.scm: -------------------------------------------------------------------------------- 1 | (define (front-ptr queue) (car queue)) 2 | (define (rear-ptr queue) (cdr queue)) 3 | (define (set-front-ptr! queue item) 4 | (set-car! queue item)) 5 | (define (set-rear-ptr! queue item) 6 | (set-cdr! queue item)) 7 | 8 | (define (empty-queue? queue) 9 | (null? (front-ptr queue))) 10 | 11 | (define (make-queue) (cons '() '())) 12 | 13 | 14 | (define (front-queue queue) 15 | (if (empty-queue? queue) 16 | (error "FRONT called with an 17 | empty queue" queue) 18 | (car (front-ptr queue)))) 19 | 20 | (define (insert-queue! queue item) 21 | (let ((new-pair (cons item '()))) 22 | (cond ((empty-queue? queue) 23 | (set-front-ptr! queue new-pair) 24 | (set-rear-ptr! queue new-pair) 25 | queue) 26 | (else (set-cdr! (rear-ptr queue) 27 | new-pair) 28 | (set-rear-ptr! queue new-pair) 29 | queue)))) 30 | 31 | 32 | (define (delete-queue! queue) 33 | (cond ((empty-queue? queue) 34 | (error "DELETE! called with 35 | an empty queue" queue)) 36 | (else (set-front-ptr! 37 | queue 38 | (cdr (front-ptr queue))) 39 | queue))) 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.01.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.1: Notice that we cannot tell whether the metacircular evaluator evaluates operands from left to right or from right to left. Its evaluation order is inherited from the underlying Lisp: If the arguments to cons in list-of-values are evaluated from left to right, then list-of-values will evaluate operands from left to right; and if the arguments to cons are evaluated from right to left, then list-of-values will evaluate operands from right to left. 2 | 3 | ; Write a version of list-of-values that evaluates operands from left to right regardless of the order of evaluation in the underlying Lisp. Also write a version of list-of-values that evaluates operands from right to left. 4 | 5 | (define (list-of-values exps env) 6 | (if (no-operands? exps) 7 | '() 8 | (cons (eval (first-operand exps) env) 9 | (list-of-values 10 | (rest-operands exps) 11 | env)))) 12 | 13 | ; left to right 14 | (define (list-of-values exps env) 15 | (if (no-operands? exps) 16 | '() 17 | (let ((first (eval (first-operand exps) env))) 18 | (cons first 19 | (list-of-values 20 | (rest-operands exps) 21 | env))))) 22 | ; right to left 23 | (define (list-of-values exps env) 24 | (if (no-operands? exps) 25 | '() 26 | (let ((rest (list-of-values 27 | (rest-operands exps) 28 | env))) 29 | (cons (eval (first-operand exps) env) 30 | (list-of-values 31 | (rest-operands exps) 32 | env))))) 33 | 34 | 35 | (cond 36 | (else 1)) -------------------------------------------------------------------------------- /Chapter4/Exercise4.14.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.14: Eva Lu Ator and Louis Reasoner are each experimenting with the metacircular evaluator. Eva types in the definition of map, and runs some test programs that use it. They work fine. Louis, in contrast, has installed the system version of map as a primitive for the metacircular evaluator. When he tries it, things go terribly wrong. Explain why Louis’s map fails even though Eva’s works. 2 | 3 | because by then, a tagged list of 'procedure would be one of the args of the bultin method map , and it did not recognize by as a procedure by the bultin evaluator. -------------------------------------------------------------------------------- /Chapter4/Exercise4.15.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.15: Given a one-argument procedure p and an object a, p is said to “halt” on a if evaluating the expression (p a) returns a value (as opposed to terminating with an error message or running forever). Show that it is impossible to write a procedure halts? that correctly determines whether p halts on a for any procedure p and object a. Use the following reasoning: If you had such a procedure halts?, you could implement the following program: 2 | 3 | ; (define (run-forever) 4 | ; (run-forever)) 5 | 6 | ; (define (try p) 7 | ; (if (halts? p p) 8 | ; (run-forever) 9 | ; 'halted)) 10 | ; Now consider evaluating the expression (try try) and show that any possible outcome (either halting or running forever) violates the intended behavior of halts?. 11 | 12 | if running forever, it is halted , if it is halted, it is running forever, no solution would come to this. -------------------------------------------------------------------------------- /Chapter4/Exercise4.18.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.18: Consider an alternative strategy for scanning out definitions that translates the example in the text to 2 | 3 | ; (lambda ⟨vars⟩ 4 | ; (let ((u '*unassigned*) 5 | ; (v '*unassigned*)) 6 | ; (let ((a ⟨e1⟩) 7 | ; (b ⟨e2⟩)) 8 | ; (set! u a) 9 | ; (set! v b)) 10 | ; ⟨e3⟩)) 11 | ; Here a and b are meant to represent new variable names, created by the interpreter, that do not appear in the user’s program. Consider the solve procedure from 3.5.4: 12 | 13 | ; (define (solve f y0 dt) 14 | ; (define y (integral (delay dy) y0 dt)) 15 | ; (define dy (stream-map f y)) 16 | ; y) 17 | ; Will this procedure work if internal definitions are scanned out as shown in this exercise? What if they are scanned out as shown in the text? Explain. 18 | 19 | ; 1 20 | as text in this exercise, it would be an error because , when dy is definning , the y would be unassigned when assigning b. 21 | ; 2 22 | whereas in the text it would be just fine because the y would be define when assigning dy the value of (stream-map f y) -------------------------------------------------------------------------------- /Chapter4/Exercise4.22.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.22: Extend the evaluator in this section to support the special form let. (See Exercise 4.6.) 2 | (load "/Users/soulomoon/git/SICP/Chapter4/separating.scm") 3 | (define (analyze exp) 4 | (cond ((self-evaluating? exp) 5 | (analyze-self-evaluating exp)) 6 | ((quoted? exp) 7 | (analyze-quoted exp)) 8 | ((variable? exp) 9 | (analyze-variable exp)) 10 | ((let? exp) 11 | (display (let->combination exp))(newline ) 12 | (analyze (let->combination exp))) 13 | ((assignment? exp) 14 | (analyze-assignment exp)) 15 | ((definition? exp) 16 | (analyze-definition exp)) 17 | ((if? exp) 18 | (analyze-if exp)) 19 | ((lambda? exp) 20 | (analyze-lambda exp)) 21 | ((begin? exp) 22 | (analyze-sequence 23 | (begin-actions exp))) 24 | ((cond? exp) 25 | (analyze (cond->if exp))) 26 | ((application? exp) 27 | (analyze-application exp)) 28 | 29 | (else 30 | (error "Unknown expression 31 | type: ANALYZE" 32 | exp)))) 33 | 34 | (define (let? exp) 35 | (tagged-list? exp 'let)) 36 | 37 | 38 | (let ((x 2) 39 | (y 3)) 40 | (if x y)) 41 | (interpret 42 | '(let ((x 2) 43 | (y 3)) 44 | (if x y))) 45 | 46 | 47 | ; Welcome to DrRacket, version 6.7 [3m]. 48 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 49 | ; 3 50 | ; ((lambda (x y) (if x y)) 2 3) 51 | ; 3 52 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.23.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.23: Alyssa P. Hacker doesn’t understand why analyze-sequence needs to be so complicated. All the other analysis procedures are straightforward transformations of the corresponding evaluation procedures (or eval clauses) in 4.1.1. She expected analyze-sequence to look like this: 2 | 3 | ; (define (analyze-sequence exps) 4 | ; (define (execute-sequence procs env) 5 | ; (cond ((null? (cdr procs)) 6 | ; ((car procs) env)) 7 | ; (else ((car procs) env) 8 | ; (execute-sequence 9 | ; (cdr procs) env)))) 10 | ; (let ((procs (map analyze exps))) 11 | ; (if (null? procs) 12 | ; (error "Empty sequence: 13 | ; ANALYZE")) 14 | ; (lambda (env) 15 | ; (execute-sequence procs env)))) 16 | ; Eva Lu Ator explains to Alyssa that the version in the text does more of the work of evaluating a sequence at analysis time. Alyssa’s sequence-execution procedure, rather than having the calls to the individual execution procedures built in, loops through the procedures in order to call them: In effect, although the individual expressions in the sequence have been analyzed, the sequence itself has not been. 17 | 18 | one: 19 | procs = ((+ 1 1)) 20 | new: (lambda (env) (execute-sequence ((lambda (env) (+ 1 1))) env)) 21 | old: (lambda (env) (+ 1 1)) 22 | two: 23 | ((+ 1 1) (- 2 2)) 24 | new: (lambda (env) (execute-sequence ((lambda (env) (+ 1 1)) (lambda (env) (- 2 2))) env)) 25 | old: (lambda (env) (((lambda (env) (+ 1 1)) env) ((lambda (env) (- 2 2)) env))) 26 | 27 | the new version have to evaluating execute-sequence which use to unfold the begin list, where as the old one make it already a nested lambda. 28 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.24.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.24: Design and carry out some experiments to compare the speed of the original metacircular evaluator with the version in this section. Use your results to estimate the fraction of time that is spent in analysis versus execution for various procedures. 2 | (load "/Users/soulomoon/git/SICP/Chapter4/ex4.03.rkt") 3 | 4 | (define (report start_time) 5 | (display " *** ") 6 | (display (- (runtime) start_time)) 7 | (newline )) 8 | 9 | 10 | 11 | (define a 12 | '(begin 13 | (define (factorial n) 14 | (if (< n 2) 15 | 1 16 | (* (factorial (- n 1)) n))) 17 | (define (fib n) 18 | (cond ((= n 0) 0) 19 | ((= n 1) 1) 20 | (else (+ (fib (- n 1)) (fib (- n 2)))))) 21 | 22 | (factorial 50) 23 | (fib 20) 24 | )) 25 | 26 | (define 27 | (runtime-interpret exp) 28 | (let ((start_time (runtime))) 29 | (display (interpret exp)) 30 | (report start_time) 31 | )) 32 | 33 | (newline )(display "without separating")(newline ) 34 | (runtime-interpret a) 35 | (runtime-interpret a) 36 | (runtime-interpret a) 37 | (load "/Users/soulomoon/git/SICP/Chapter4/separating.scm") 38 | (newline )(display "separating")(newline ) 39 | (runtime-interpret a) 40 | (runtime-interpret a) 41 | (runtime-interpret a) 42 | 43 | ; took about half of the time when separating eval and analysis 44 | ; Welcome to DrRacket, version 6.7 [3m]. 45 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 46 | 47 | ; without separating 48 | ; 6765 *** 622443 49 | ; 6765 *** 620444 50 | ; 6765 *** 603262 51 | 52 | ; separating 53 | ; 6765 *** 351626 54 | ; 6765 *** 273320 55 | ; 6765 *** 345168 56 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.25.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.25: Suppose that (in ordinary applicative-order Scheme) we define unless as shown above and then define factorial in terms of unless as 2 | 3 | ; (define (factorial n) 4 | ; (unless (= n 1) 5 | ; (* n (factorial (- n 1))) 6 | ; 1)) 7 | ; What happens if we attempt to evaluate (factorial 5)? Will our definitions work in a normal-order language? 8 | 9 | ; it would work in noraml-order not applicative-order. 10 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.28.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.28: Eval uses actual-value rather than eval to evaluate the operator before passing it to apply, in order to force the value of the operator. Give an example that demonstrates the need for this forcing. 2 | 3 | (define (id x) x) 4 | ((id +) 1 1) 5 | 6 | eval id is a compund procedure, which mean + woule be delay-it'ed. 7 | so you have to force-it to get + back. 8 | ; Welcome to DrRacket, version 6.7 [3m]. 9 | ; Language: SICP (PLaneT 1.18); memory limit: 128 MB. 10 | ; 'done 11 | ; eval#-----(begin (define (id x) x) ((id +) 1 1)) 12 | ; eval#-----(define (id x) x) 13 | ; eval#-----(lambda (x) x) 14 | ; eval#-----((id +) 1 1) 15 | ; eval#-----(id +) 16 | ; eval#-----id 17 | ; delay-it--------+ 18 | ; eval#-----x 19 | ; eval#-----+ 20 | ; force-it------thunk+ 21 | ; eval#-----1 22 | ; eval#-----1 23 | ; 2 24 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.29.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.29: Exhibit a program that you would expect to run much more slowly without memoization than with memoization. Also, consider the following interaction, where the id procedure is defined as in Exercise 4.27 and count starts at 0: 2 | 3 | ; (define (square x) (* x x)) 4 | 5 | ; ;;; L-Eval input: 6 | ; (square (id 10)) 7 | 8 | ; ;;; L-Eval value: 9 | ; ⟨response⟩ 10 | 11 | ; ;;; L-Eval input: 12 | ; count 13 | 14 | ; ;;; L-Eval value: 15 | ; ⟨response⟩ 16 | ; Give the responses both when the evaluator memoizes and when it does not. 17 | 18 | is: 19 | ;;; L-Eval input: 20 | (square (id 10)) 21 | 22 | ;;; L-Eval value: 23 | 100 24 | 25 | ;;; L-Eval input: 26 | count 27 | 28 | ;;; L-Eval value: 29 | 1 30 | 31 | not: 32 | ;;; L-Eval input: 33 | (square (id 10)) 34 | 35 | ;;; L-Eval value: 36 | 100 37 | 38 | ;;; L-Eval input: 39 | count 40 | 41 | ;;; L-Eval value: 42 | 2 43 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.32.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.32: Give some examples that illustrate the difference between the streams of Chapter 3 and the “lazier” lazy lists described in this section. How can you take advantage of this extra laziness? 2 | 3 | ; both car and cdr is delayed 4 | ; which means you can define somthing like this 5 | 6 | (define (test) 7 | (define a cons(c c)) 8 | (define c 2) 9 | a 10 | ) 11 | 12 | ; easier for simultaneous -------------------------------------------------------------------------------- /Chapter4/Exercise4.35.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.35: Write a procedure an-integer-between that returns an integer between two given bounds. This can be used to implement a procedure that finds Pythagorean triples, i.e., triples of integers (i,j,k)(i,j,k) between the given bounds such that i≤ji≤j and i2+j2=k2i2+j2=k2, as follows: 2 | 3 | ; (define (a-pythagorean-triple-between low high) 4 | ; (let ((i (an-integer-between low high))) 5 | ; (let ((j (an-integer-between i high))) 6 | ; (let ((k (an-integer-between j high))) 7 | ; (require (= (+ (* i i) (* j j)) 8 | ; (* k k))) 9 | ; (list i j k))))) 10 | 11 | #lang swindle 12 | 13 | 14 | (define (square x) (* x x)) 15 | (define (require p) 16 | (if (not p) (amb))) 17 | (define (an-integer-between low high) 18 | (require (<= low high)) 19 | (amb low (an-integer-between (+ low 1) high))) 20 | 21 | (define (a-pythagorean-triple-between low high) 22 | (let* ((i (an-integer-between low high)) 23 | (j (an-integer-between i high)) 24 | (k (an-integer-between j high))) 25 | (require (= (+ (square i) (square j)) 26 | (square k))) 27 | (list i j k))) 28 | (print (amb-collect (a-pythagorean-triple-between 1 100))) 29 | 30 | 31 | ; Welcome to DrRacket, version 6.7 [3m]. 32 | ; Language: swindle, with debugging; memory limit: 128 MB. 33 | ; ((3 4 5) (5 12 13) (6 8 10) (7 24 25) (8 15 17) (9 12 15) (9 40 41) (10 24 26) (11 60 61) (12 16 20) (12 35 37) (13 84 85) (14 48 50) (15 20 25) (15 36 39) (16 30 34) (16 63 65) (18 24 30) (18 80 82) (20 21 29) ...) 34 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.36.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.36: Exercise 3.69 discussed how to generate the stream of all Pythagorean triples, with no upper bound on the size of the integers to be searched. Explain why simply replacing an-integer-between by an-integer-starting-from in the procedure in Exercise 4.35 is not an adequate way to generate arbitrary Pythagorean triples. Write a procedure that actually will accomplish this. (That is, write a procedure for which repeatedly typing try-again would in principle eventually generate all Pythagorean triples.) 2 | 3 | ; because it would nerver stop 4 | 5 | 6 | #lang swindle 7 | 8 | 9 | (define (square x) (* x x)) 10 | (define (require p) 11 | (if (not p) (amb))) 12 | (define (an-integer-between low high) 13 | (require (<= low high)) 14 | (amb low (an-integer-between (+ low 1) high))) 15 | (define (an-element-of items) 16 | (require (not (null? items))) 17 | (amb (car items) 18 | (an-element-of (cdr items)))) 19 | (define (an-integer-starting-from n) 20 | (amb n (an-integer-starting-from (+ n 1)))) 21 | 22 | 23 | 24 | (define (a-pythagorean-triple-from high) 25 | (let* ((k (an-integer-starting-from high)) 26 | (j (an-integer-between 1 k)) 27 | (i (an-integer-between 1 j))) 28 | (require (= (+ (square i) (square j)) 29 | (square k))) 30 | (list i j k))) 31 | 32 | 33 | (print (a-pythagorean-triple-from 33)) 34 | 35 | 36 | ; Welcome to DrRacket, version 6.7 [3m]. 37 | ; Language: swindle, with debugging; memory limit: 128 MB. 38 | ; (16 30 34) 39 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.37.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.37: Ben Bitdiddle claims that the following method for generating Pythagorean triples is more efficient than the one in Exercise 4.35. Is he correct? (Hint: Consider the number of possibilities that must be explored.) 2 | 3 | ; (define (a-pythagorean-triple-between low high) 4 | ; (let ((i (an-integer-between low high)) 5 | ; (hsq (* high high))) 6 | ; (let ((j (an-integer-between i high))) 7 | ; (let ((ksq (+ (* i i) (* j j)))) 8 | ; (require (>= hsq ksq)) 9 | ; (let ((k (sqrt ksq))) 10 | ; (require (integer? k)) 11 | ; (list i j k)))))) 12 | 13 | ; from n^3 to n^2 14 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.38.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.38: Modify the multiple-dwelling procedure to omit the requirement that Smith and Fletcher do not live on adjacent floors. How many solutions are there to this modified puzzle? 2 | 3 | #lang swindle 4 | 5 | (define (square x) (* x x)) 6 | (define (require p) 7 | (if (not p) (amb))) 8 | (define (an-integer-between low high) 9 | (require (<= low high)) 10 | (amb low (an-integer-between (+ low 1) high))) 11 | 12 | (define (distinct? items) 13 | (cond ((null? items) true) 14 | ((null? (cdr items)) true) 15 | ((member (car items) (cdr items)) false) 16 | (else (distinct? (cdr items))))) 17 | 18 | (define (multiple-dwelling) 19 | (let ((baker (amb 1 2 3 4 5)) 20 | (cooper (amb 1 2 3 4 5)) 21 | (fletcher (amb 1 2 3 4 5)) 22 | (miller (amb 1 2 3 4 5)) 23 | (smith (amb 1 2 3 4 5))) 24 | (require 25 | (distinct? (list baker cooper fletcher 26 | miller smith))) 27 | (require (not (= baker 5))) 28 | (require (not (= cooper 1))) 29 | (require (not (= fletcher 5))) 30 | (require (not (= fletcher 1))) 31 | (require (> miller cooper)) 32 | (require 33 | (not (= (abs (- fletcher cooper)) 1))) 34 | (list (list 'baker baker) 35 | (list 'cooper cooper) 36 | (list 'fletcher fletcher) 37 | (list 'miller miller) 38 | (list 'smith smith)))) 39 | (for-each (lambda (x) (display x)(newline )) (amb-collect (multiple-dwelling))) 40 | 41 | ; Welcome to DrRacket, version 6.7 [3m]. 42 | ; Language: swindle, with debugging; memory limit: 128 MB. 43 | ; ((baker 1) (cooper 2) (fletcher 4) (miller 3) (smith 5)) 44 | ; ((baker 1) (cooper 2) (fletcher 4) (miller 5) (smith 3)) 45 | ; ((baker 1) (cooper 4) (fletcher 2) (miller 5) (smith 3)) 46 | ; ((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1)) 47 | ; ((baker 3) (cooper 4) (fletcher 2) (miller 5) (smith 1)) 48 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.44.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.44: Exercise 2.42 described the “eight-queens puzzle” of placing queens on a chessboard so that no two attack each other. Write a nondeterministic program to solve this puzzle. 2 | #lang swindle 3 | (define (an-element-of items) 4 | (require (not (null? items))) 5 | (amb (car items) 6 | (an-element-of (cdr items)))) 7 | 8 | (define (require p) 9 | (if (not p) (amb))) 10 | (define (distinct? items) 11 | (cond ((null? items) true) 12 | ((null? (cdr items)) true) 13 | ((member (car items) (cdr items)) false) 14 | (else (distinct? (cdr items))))) 15 | 16 | (define (num) (amb 1 2 3 4 5 6 7 8)) 17 | (define all_rows (list 1 2 3 4 5 6 7 8)) 18 | (define all_queens (list 'q1 'q2 'q3 'q4 'q5 'q6 'q7 'q8)) 19 | (define (position x) (list x (num))) 20 | (define (solve-queens) 21 | (let* ((queens 22 | (map 23 | (lambda (r queen) 24 | (list queen (position r))) 25 | all_rows 26 | all_queens)) 27 | (cols (map caadr queens))) 28 | (require 29 | (distinct? cols)) 30 | queens)) 31 | 32 | (display (solve-queens)) 33 | 34 | 35 | ; Welcome to DrRacket, version 6.7 [3m]. 36 | ; Language: swindle, with debugging; memory limit: 2048 MB. 37 | ; ((q1 (1 1)) (q2 (2 1)) (q3 (3 1)) (q4 (4 1)) (q5 (5 1)) (q6 (6 1)) (q7 (7 1)) (q8 (8 1))) 38 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.46.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.46: The evaluators in 4.1 and 4.2 do not determine what order operands are evaluated in. We will see that the amb evaluator evaluates them from left to right. Explain why our parsing program wouldn’t work if the operands were evaluated in some other order. 2 | 3 | because the it use set!, it relies on the order. and we have written it to be left to right, other order won't work -------------------------------------------------------------------------------- /Chapter4/Exercise4.47.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.47: Louis Reasoner suggests that, since a verb phrase is either a verb or a verb phrase followed by a prepositional phrase, it would be much more straightforward to define the procedure parse-verb-phrase as follows (and similarly for noun phrases): 2 | 3 | ; (define (parse-verb-phrase) 4 | ; (amb (parse-word verbs) 5 | ; (list 6 | ; 'verb-phrase 7 | ; (parse-verb-phrase) 8 | ; (parse-prepositional-phrase)))) 9 | ; Does this work? Does the program’s behavior change if we interchange the order of expressions in the amb? 10 | 11 | it is an infinite loop - -// (eval from left to right) 12 | if it is from right to left, it can stop, but the behavior still wrong -------------------------------------------------------------------------------- /Chapter4/Exercise4.49.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.49: Alyssa P. Hacker is more interested in generating interesting sentences than in parsing them. She reasons that by simply changing the procedure parse-word so that it ignores the “input sentence” and instead always succeeds and generates an appropriate word, we can use the programs we had built for parsing to do generation instead. Implement Alyssa’s idea, and show the first half-dozen or so sentences generated.258 2 | 3 | (load "/Users/soulomoon/git/SICP/Chapter4/nlpparser.scm") 4 | 5 | (interpret '(define (an-element-of items) 6 | (require (not (null? items))) 7 | (amb (car items) 8 | (an-element-of (cdr items))))) 9 | 10 | 11 | 12 | (interpret '(define (parse-word word-list) 13 | (require (not (null? *unparsed*))) 14 | (require (memq (car *unparsed*) 15 | (cdr word-list))) 16 | (let ((found-word (car *unparsed*))) 17 | (set! *unparsed* (cdr *unparsed*)) 18 | (list (car word-list) (an-element-of (cdr word-list)))))) 19 | 20 | (interpret '(display (parse '(the professor lectures to the student in the class with the cat)))) 21 | 22 | (try-again) 23 | (try-again) 24 | (try-again) 25 | (try-again) 26 | (try-again) 27 | (try-again) 28 | (try-again) -------------------------------------------------------------------------------- /Chapter4/Exercise4.55.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.55: Give simple queries that retrieve the following information from the data base: 2 | 3 | ; all people supervised by Ben Bitdiddle; 4 | ; the names and jobs of all people in the accounting division; 5 | ; the names and addresses of all people who live in Slumerville. 6 | 7 | 8 | ; loading is from "https://wizardbook.wordpress.com/2011/01/24/exercise-4-55/" 9 | ; I use iq as interpret-query. 10 | ; thankx for Barry Allison that I could continue my exercise 11 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 12 | 13 | 14 | (iq '(supervisor ?name (Bitdiddle Ben))) 15 | (iq '(job ?name (accounting . ?y))) 16 | (iq '(address ?name (Slumerville . ?y))) 17 | 18 | 19 | ; Welcome to DrRacket, version 6.7 [3m]. 20 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 21 | ; 'done 22 | 23 | 24 | ; (supervisor (Tweakit Lem E) (Bitdiddle Ben)) 25 | ; (supervisor (Fect Cy D) (Bitdiddle Ben)) 26 | ; (supervisor (Hacker Alyssa P) (Bitdiddle Ben)) 27 | 28 | 29 | ; (job (Cratchet Robert) (accounting scrivener)) 30 | ; (job (Scrooge Eben) (accounting chief accountant)) 31 | 32 | 33 | ; (address (Aull DeWitt) (Slumerville (Onion Square) 5)) 34 | ; (address (Reasoner Louis) (Slumerville (Pine Tree Road) 80)) 35 | ; (address (Bitdiddle Ben) (Slumerville (Ridge Road) 10)) 36 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.57.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.57: Define a rule that says that person 1 can replace person 2 if either person 1 does the same job as person 2 or someone who does person 1’s job can also do person 2’s job, and if person 1 and person 2 are not the same person. Using your rule, give queries that find the following: 2 | 3 | ; all people who can replace Cy D. Fect; 4 | ; all people who can replace someone who is being paid more than they are, together with the two salaries. 5 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 6 | 7 | 8 | (iqe 9 | '(assert! 10 | (rule (replace ?p1 ?p2) 11 | (and (and (job ?p1 ?dj1) 12 | (job ?p2 ?dj2)) 13 | (not (same ?p1 ?p2)) 14 | (or (same ?dj1 ?dj2) 15 | (can-do-job ?dj1 ?dj2))))) 16 | '(replace ?p (Fect Cy D)) 17 | 18 | '(and (replace ?p1 ?p2) 19 | (salary ?p1 ?a1) 20 | (salary ?p2 ?a2) 21 | (lisp-value < ?a1 ?a2) 22 | ) 23 | 24 | ) 25 | 26 | ; Welcome to DrRacket, version 6.7 [3m]. 27 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 28 | 29 | ; Assertion added to data base. 30 | 31 | ; (replace (Hacker Alyssa P) (Fect Cy D)) 32 | ; (replace (Bitdiddle Ben) (Fect Cy D)) 33 | 34 | 35 | ; (and (replace (Fect Cy D) (Hacker Alyssa P)) (salary (Fect Cy D) 35000) (salary (Hacker Alyssa P) 40000) (lisp-value < 35000 40000)) 36 | ; (and (replace (Aull DeWitt) (Warbucks Oliver)) (salary (Aull DeWitt) 25000) (salary (Warbucks Oliver) 150000) (lisp-value < 25000 150000)) 37 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.58.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.58: Define a rule that says that a person is a “big shot” in a division if the person works in the division but does not have a supervisor who works in the division. 2 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 3 | 4 | (iqe 5 | '(assert! 6 | (rule (bigshot ?p1) 7 | (and (job ?p1 (?div1 . ?x1)) 8 | (or (not (supervisor ?p1 ?p2)) 9 | (and 10 | (supervisor ?p1 ?p2) 11 | (job ?p2 (?div2 . ?x2)) 12 | (not (same ?div1 ?div2))))))) 13 | '(bigshot ?p1) 14 | 15 | ) 16 | 17 | 18 | ; Welcome to DrRacket, version 6.7 [3m]. 19 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 20 | 21 | ; Assertion added to data base. 22 | 23 | ; (bigshot (Warbucks Oliver)) 24 | ; (bigshot (Scrooge Eben)) 25 | ; (bigshot (Bitdiddle Ben)) 26 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.61.scm: -------------------------------------------------------------------------------- 1 | 2 | ; Exercise 4.61: The following rules implement a next-to relation that finds adjacent elements of a list: 3 | 4 | ; (rule (?x next-to ?y in (?x ?y . ?u))) 5 | ; (rule (?x next-to ?y in (?v . ?z)) 6 | ; (?x next-to ?y in ?z)) 7 | ; What will the response be to the following queries? 8 | 9 | ; (?x next-to ?y in (1 (2 3) 4)) 10 | ; (?x next-to 1 in (2 1 3 1)) 11 | 12 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 13 | 14 | ; That I have to put the rule in setup in order for it to work 15 | 16 | (define (inssert_to_init rule_list) 17 | (for-each (lambda (rule) (set! microshaft-data-base (cons rule microshaft-data-base))) rule_list) 18 | (setup-data-base)) 19 | 20 | (inssert_to_init '( 21 | (rule (?x next-to ?y in (?x ?y . ?u))) 22 | (rule (?x next-to ?y in (?v . ?z)) 23 | (?x next-to ?y in ?z)) 24 | )) 25 | 26 | (inqu'( 27 | 28 | (?x next-to ?y in (1 (2 3) 4)) 29 | (?x next-to 1 in (2 1 3 1)) 30 | 31 | )) -------------------------------------------------------------------------------- /Chapter4/Exercise4.62.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.62: Define rules to implement the last-pair operation of Exercise 2.17, which returns a list containing the last element of a nonempty list. Check your rules on queries such as (last-pair (3) ?x), (last-pair (1 2 3) ?x) and (last-pair (2 ?x) (3)). Do your rules work correctly on queries such as (last-pair ?x (3))? 2 | 3 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 4 | 5 | (inssert_to_init '( 6 | (rule (last-pair (?x) (?x))) 7 | (rule (last-pair (?v . ?z) (?x)) 8 | (last-pair ?z (?x))) 9 | )) 10 | 11 | (inqu'( 12 | (last-pair (3) ?x) 13 | (last-pair (1 2 3) ?x) 14 | (last-pair (2 ?x) (3)) 15 | )) 16 | 17 | ; it won't work with (last-pair ?x (3)) because there are ways to make up ?x 18 | 19 | ; Welcome to DrRacket, version 6.7 [3m]. 20 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 21 | ; 'done 22 | 23 | 24 | ; (last-pair (3) (3)) 25 | 26 | 27 | ; (last-pair (1 2 3) (3)) 28 | 29 | 30 | ; (last-pair (2 3) (3)) 31 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.64.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.64: Louis Reasoner mistakenly deletes the outranked-by rule (4.4.1) from the data base. When he realizes this, he quickly reinstalls it. Unfortunately, he makes a slight change in the rule, and types it in as 2 | 3 | ; (rule (outranked-by ?staff-person ?boss) 4 | ; (or (supervisor ?staff-person ?boss) 5 | ; (and (outranked-by ?middle-manager 6 | ; ?boss) 7 | ; (supervisor ?staff-person 8 | ; ?middle-manager)))) 9 | ; Just after Louis types this information into the system, DeWitt Aull comes by to find out who outranks Ben Bitdiddle. He issues the query 10 | 11 | ; (outranked-by (Bitdiddle Ben) ?who) 12 | ; After answering, the system goes into an infinite loop. Explain why. 13 | 14 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 15 | 16 | ; because the first clause of and called the rule itself, which does not provided a way to sufficiantly filter out the unneeded part. -------------------------------------------------------------------------------- /Chapter4/Exercise4.65.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.65: Cy D. Fect, looking forward to the day when he will rise in the organization, gives a query to find all the wheels (using the wheel rule of 4.4.1): 2 | 3 | ; (wheel ?who) 4 | ; To his surprise, the system responds 5 | 6 | ; ;;; Query results: 7 | ; (wheel (Warbucks Oliver)) 8 | ; (wheel (Bitdiddle Ben)) 9 | ; (wheel (Warbucks Oliver)) 10 | ; (wheel (Warbucks Oliver)) 11 | ; (wheel (Warbucks Oliver)) 12 | ; Why is Oliver Warbucks listed four times? 13 | 14 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 15 | 16 | (inqu '( 17 | (wheel ?x) 18 | (and (supervisor ?middle-manager 19 | ?person) 20 | (supervisor ?x ?middle-manager)) 21 | )) 22 | 23 | ; because he has four ways of being a wheel as show below 24 | 25 | ; Welcome to DrRacket, version 6.7 [3m]. 26 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 27 | 28 | 29 | ; (wheel (Warbucks Oliver)) 30 | ; (wheel (Warbucks Oliver)) 31 | ; (wheel (Bitdiddle Ben)) 32 | ; (wheel (Warbucks Oliver)) 33 | ; (wheel (Warbucks Oliver)) 34 | 35 | 36 | ; (and (supervisor (Scrooge Eben) (Warbucks Oliver)) (supervisor (Cratchet Robert) (Scrooge Eben))) 37 | ; (and (supervisor (Bitdiddle Ben) (Warbucks Oliver)) (supervisor (Tweakit Lem E) (Bitdiddle Ben))) 38 | ; (and (supervisor (Hacker Alyssa P) (Bitdiddle Ben)) (supervisor (Reasoner Louis) (Hacker Alyssa P))) 39 | ; (and (supervisor (Bitdiddle Ben) (Warbucks Oliver)) (supervisor (Fect Cy D) (Bitdiddle Ben))) 40 | ; (and (supervisor (Bitdiddle Ben) (Warbucks Oliver)) (supervisor (Hacker Alyssa P) (Bitdiddle Ben))) 41 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.66.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.66: Ben has been generalizing the query system to provide statistics about the company. For example, to find the total salaries of all the computer programmers one will be able to say 2 | 3 | ; (sum ?amount 4 | ; (and (job ?x (computer programmer)) 5 | ; (salary ?x ?amount))) 6 | ; In general, Ben’s new system allows expressions of the form 7 | 8 | ; (accumulation-function ⟨variable⟩ 9 | ; ⟨query pattern⟩) 10 | ; where accumulation-function can be things like sum, average, or maximum. Ben reasons that it should be a cinch to implement this. He will simply feed the query pattern to qeval. This will produce a stream of frames. He will then pass this stream through a mapping function that extracts the value of the designated variable from each frame in the stream and feed the resulting stream of values to the accumulation function. Just as Ben completes the implementation and is about to try it out, Cy walks by, still puzzling over the wheel query result in Exercise 4.65. When Cy shows Ben the system’s response, Ben groans, “Oh, no, my simple accumulation scheme won’t work!” 11 | 12 | ; What has Ben just realized? Outline a method he can use to salvage the situation. 13 | 14 | ; there would be duplicate. 15 | ; way to solve it is to eliminate the duplicate. 16 | ; that he can keep track on the a frame of variable that has already be in the accumulation, and ignore duplicate. -------------------------------------------------------------------------------- /Chapter4/Exercise4.67.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.67: Devise a way to install a loop detector in the query system so as to avoid the kinds of simple loops illustrated in the text and in Exercise 4.64. The general idea is that the system should maintain some sort of history of its current chain of deductions and should not begin processing a query that it is already working on. Describe what kind of information (patterns and frames) is included in this history, and how the check should be made. (After you study the details of the query-system implementation in 4.4.4, you may want to modify the system to include your loop detector.) 2 | 3 | ; if is has the same patterns and frams as in the history, it would be infinite loop. -------------------------------------------------------------------------------- /Chapter4/Exercise4.68.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.68: Define rules to implement the reverse operation of Exercise 2.18, which returns a list containing the same elements as a given list in reverse order. (Hint: Use append-to-form.) Can your rules answer both (reverse (1 2 3) ?x) and (reverse ?x (1 2 3))? 2 | 3 | (load "/Users/soulomoon/git/SICP/Chapter4/ch4-query.rkt") 4 | 5 | (inssert_to_init 6 | '( 7 | 8 | (rule (append-to-form () ?y ?y)) 9 | (rule (append-to-form (?u . ?v) ?y (?u . ?z)) 10 | (append-to-form ?v ?y ?z)) 11 | 12 | (rule (last-pair (?x) (?x))) 13 | (rule (last-pair (?v . ?z) (?x)) 14 | (last-pair ?z (?x))) 15 | 16 | 17 | (rule (reverse (?a ?b) (?b ?a))) 18 | (rule (reverse (?a ?b ?c) (?c ?b ?a))) 19 | (rule (reverse (?a) (?a))) 20 | (rule (reverse ?a (?c ?c1 . ?d)) 21 | (and 22 | (same ?d (?k0 ?k1 . ?g)) 23 | ; (append-to-form ?list1 (?a) (?c . ?d)) 24 | (append-to-form ?list2 (?c1 ?c) ?a) 25 | (reverse ?list2 ?d) 26 | ; (reverse ?list1 (?c . ?d)) 27 | ; (reverse ?list1 ?b) 28 | 29 | ) 30 | ) 31 | ) 32 | (inqu 33 | '( 34 | (reverse (2 3) ?x) 35 | (reverse (1 2 3) ?x) 36 | (reverse ?x (1 2 3)) 37 | (reverse (1 2 3 4) ?x) 38 | (reverse ?x (1 2 3 4)) 39 | ) 40 | ) 41 | ; manage to get the answer working by hand, but with the case there are more numbers, 42 | ; right side variable get a answer and stuck, need to implement detector for infinite loop 43 | 44 | ; Welcome to DrRacket, version 6.7 [3m]. 45 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 46 | ; 'done 47 | 48 | 49 | ; (reverse (2 3) (3 2)) 50 | 51 | 52 | ; (reverse (1 2 3) (3 2 1)) 53 | 54 | 55 | ; (reverse (3 2 1) (1 2 3)) 56 | 57 | 58 | ; (reverse (1 2 3 4) (4 3 2 1)) 59 | 60 | 61 | ; (reverse (4 3 2 1) (1 2 3 4)). . git/SICP/Chapter4/ch4-query.rkt:468:2: user break 62 | ; > -------------------------------------------------------------------------------- /Chapter4/Exercise4.70.md: -------------------------------------------------------------------------------- 1 | ; Exercise 4.70: What is the purpose of the let bindings in the procedures add-assertion! and add-rule!? What would be wrong with the following implementation of add-assertion!? Hint: Recall the definition of the infinite stream of ones in 3.5.2: (define ones (cons-stream 1 ones)). 2 | ```scheme 3 | (define (add-assertion! assertion) 4 | (store-assertion-in-index assertion) 5 | (set! THE-ASSERTIONS 6 | (cons-stream assertion 7 | THE-ASSERTIONS)) 8 | 'ok) 9 | ``` 10 | for cons-stream, the later var is delayed 11 | 12 | for ones definition, it would loopingly interpret ones, when cdring the stream list 13 | 14 | same is true for under 15 | ```scheme 16 | (set! THE-ASSERTIONS 17 | (cons-stream assertion 18 | THE-ASSERTIONS)) 19 | ``` 20 | but there is a defferent case when you stored it in a new var 21 | 22 | ```scheme 23 | (define (add-assertion! assertion) 24 | (store-assertion-in-index assertion) 25 | (let ((old-assertions THE-ASSERTIONS)) 26 | (set! THE-ASSERTIONS 27 | (cons-stream assertion 28 | old-assertions)) 29 | 'ok)) 30 | ``` 31 | 32 | the `(let ((old-assertions THE-ASSERTIONS))` here 33 | let `old-assertions` take the value of `THE-ASSERTIONS`. 34 | would strip out the outer layer which is a pointer 35 | 36 | same here: 37 | ```scheme 38 | (define a 1) 39 | (define b a) 40 | (set! a 2) 41 | b 42 | ``` 43 | as you can see, b would change with a even if a new value has 44 | been assign to a. -------------------------------------------------------------------------------- /Chapter4/Exercise4.71.md: -------------------------------------------------------------------------------- 1 | ; Exercise 4.71: Louis Reasoner wonders why the simple-query and disjoin procedures (4.4.4.2) are implemented using explicit delay operations, rather than being defined as follows: 2 | 3 | ```scheme 4 | (define (simple-query 5 | query-pattern frame-stream) 6 | (stream-flatmap 7 | (lambda (frame) 8 | (stream-append 9 | (find-assertions query-pattern frame) 10 | (apply-rules query-pattern frame))) 11 | frame-stream)) 12 | 13 | (define (disjoin disjuncts frame-stream) 14 | (if (empty-disjunction? disjuncts) 15 | the-empty-stream 16 | (interleave 17 | (qeval (first-disjunct disjuncts) 18 | frame-stream) 19 | (disjoin (rest-disjuncts disjuncts) 20 | frame-stream)))) 21 | ``` 22 | 23 | ; Can you give examples of queries where these simpler definitions would lead to undesirable behavior? 24 | 25 | 26 | in the case where a rule may lead to infinit loop, and there is also a assertions, 27 | that you can at least display the assertions that match, and then went crazy while the first rule went crazy. 28 | 29 | ```scheme 30 | (define (stream-append-delayed s1 delayed-s2) 31 | (if (stream-null? s1) 32 | (force delayed-s2) 33 | (cons-stream 34 | (stream-car s1) 35 | (stream-append-delayed (stream-cdr s1) 36 | delayed-s2)))) 37 | ``` 38 | which you can see here, cons-stream does not force the 39 | ```scheme 40 | (stream-append-delayed (stream-cdr s1) 41 | delayed-s2)))) 42 | ``` 43 | until it is force by the the program, 44 | going through simple-query, qeval, instantiate does not force it. 45 | only going to the `display-stream` it was forced and display. 46 | 47 | the same goes for `interleave-delayed` 48 | 49 | case you could find inthe book the married 50 | -------------------------------------------------------------------------------- /Chapter4/Exercise4.72.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.72: Why do disjoin and stream-flatmap interleave the streams rather than simply append them? Give examples that illustrate why interleaving works better. (Hint: Why did we use interleave in 3.5.3?) 2 | 3 | because disjoin is have two match, when we interleave it, either result come out one then another. 4 | for infinite case, it would be able to list all posibility -------------------------------------------------------------------------------- /Chapter4/Exercise4.73.md: -------------------------------------------------------------------------------- 1 | ; Exercise 4.73: Why does flatten-stream use delay explicitly? What would be wrong with defining it as follows: 2 | 3 | ; (define (flatten-stream stream) 4 | ; (if (stream-null? stream) 5 | ; the-empty-stream 6 | ; (interleave (stream-car stream) 7 | ; (flatten-stream 8 | ; (stream-cdr stream))))) 9 | 10 | the same reason for 4.71 -------------------------------------------------------------------------------- /Chapter4/Exercise4.74.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.74: Alyssa P. Hacker proposes to use a simpler version of stream-flatmap in negate, lisp-value, and find-assertions. She observes that the procedure that is mapped over the frame stream in these cases always produces either the empty stream or a singleton stream, so no interleaving is needed when combining these streams. 2 | 3 | ; Fill in the missing expressions in Alyssa’s program. 4 | ; (define (simple-stream-flatmap proc s) 5 | ; (simple-flatten (stream-map proc s))) 6 | 7 | ; (define (simple-flatten stream) 8 | ; (stream-map ⟨??⟩ 9 | ; (stream-filter ⟨??⟩ 10 | ; stream))) 11 | ; Does the query system’s behavior change if we change it in this way? 12 | (load "/Users/soulomoon/git/SICP/Chapter4/query-system.scm") 13 | (define (simple-flatten stream) 14 | (stream-map (lambda (s) (stream-car s)) 15 | (stream-filter (lambda (s) (not (stream-null? s))) 16 | stream))) 17 | 18 | (define a 19 | (simple-flatten 20 | (cons-stream 21 | (cons-stream 'a nil) 22 | (cons-stream 23 | (cons-stream 'b nil) 24 | nil)))) 25 | 26 | a 27 | (stream-cdr a) 28 | 29 | ; Welcome to DrRacket, version 6.7 [3m]. 30 | ; Language: SICP (PLaneT 1.18); memory limit: 2048 MB. 31 | ; {mcons 'a #} 32 | ; {mcons 'b #} 33 | ; > -------------------------------------------------------------------------------- /Chapter4/lazylist.scm: -------------------------------------------------------------------------------- 1 | (load "/Users/soulomoon/git/SICP/Chapter4/lazyeval.scm") 2 | 3 | 4 | 5 | (interpret 6 | '(begin 7 | (define (cons x y) (list 'lazy (lambda (m) (m x y)))) 8 | (define (car z) ((cadr z) (lambda (p q) p))) 9 | (define (cdr z) ((cadr z) (lambda (p q) q))) 10 | (define (list-ref items n) 11 | (if (= n 0) 12 | (car items) 13 | (list-ref (cdr items) (- n 1)))) 14 | (define (map proc items) 15 | (if (null? items) 16 | '() 17 | (cons (proc (car items)) 18 | (map proc (cdr items))))) 19 | (define (scale-list items factor) 20 | (map (lambda (x) (* x factor)) 21 | items)) 22 | (define (add-lists list1 list2) 23 | (cond ((null? list1) list2) 24 | ((null? list2) list1) 25 | (else (cons (+ (car list1) 26 | (car list2)) 27 | (add-lists 28 | (cdr list1) 29 | (cdr list2)))))) 30 | 31 | ; (define ones (cons 1 ones)) 32 | ; (define integers 33 | ; (cons 1 (add-lists ones integers))) 34 | ; (define a 1) 35 | )) 36 | 37 | (define (eval-quoted exp env) 38 | (text-of-quotation exp env)) 39 | 40 | (define (text-of-quotation exp env) 41 | (let ((result (cadr exp))) 42 | (if (pair? result) 43 | (eval# (make-list result) env) 44 | result))) 45 | 46 | (define (make-list result) 47 | (if (null? result) 48 | '() 49 | (list 'cons 50 | (list 'quote (car result)) 51 | (make-list (cdr result))))) 52 | (put-syntax! 'quote eval-quoted) 53 | 54 | ; (driver-loop) 55 | ; (interpret 56 | ; ''(1 2 3) 57 | ; ) -------------------------------------------------------------------------------- /Chapter4/prompt.scm: -------------------------------------------------------------------------------- 1 | (load "/Users/soulomoon/git/SICP/Chapter4/ex4.03.rkt") 2 | (define (setup-environment) 3 | (let ((initial-env 4 | (extend-environment 5 | (primitive-procedure-names) 6 | (primitive-procedure-objects) 7 | the-empty-environment))) 8 | (define-variable! 'true true initial-env) 9 | (define-variable! 'false false initial-env) 10 | initial-env)) 11 | 12 | (define the-global-environment 13 | (setup-environment)) 14 | 15 | 16 | (define (primitive-procedure? proc) 17 | (tagged-list? proc 'primitive)) 18 | 19 | (define (primitive-implementation proc) 20 | (cadr proc)) 21 | 22 | 23 | (define (primitive-procedure-names) 24 | (map car primitive-procedures)) 25 | 26 | (define (primitive-procedure-objects) 27 | (map (lambda (proc) 28 | (list 'primitive (cadr proc))) 29 | primitive-procedures)) 30 | 31 | (define (apply-primitive-procedure proc args) 32 | (apply-in-underlying-scheme 33 | (primitive-implementation proc) args)) 34 | 35 | (define input-prompt ";;; M-Eval input:") 36 | (define output-prompt ";;; M-Eval value:") 37 | 38 | (define (driver-loop) 39 | (prompt-for-input input-prompt) 40 | (let ((input (read))) 41 | (let ((output 42 | (eval# input 43 | the-global-environment))) 44 | (announce-output output-prompt) 45 | (user-print output))) 46 | (driver-loop)) 47 | 48 | (define (prompt-for-input string) 49 | (newline) (newline) 50 | (display string) (newline)) 51 | 52 | (define (announce-output string) 53 | (newline) (display string) (newline)) 54 | 55 | 56 | (define (user-print object) 57 | (if (compound-procedure? object) 58 | (display 59 | (list 'compound-procedure 60 | (procedure-parameters object) 61 | (procedure-body object) 62 | ')) 63 | (display object))) 64 | 65 | (define the-global-environment 66 | (setup-environment)) 67 | 68 | 69 | -------------------------------------------------------------------------------- /Chapter4/run-interpreter.scm: -------------------------------------------------------------------------------- 1 | ; Translation procedures: 2 | ; 3 | ; ex4.03.rkt is using the neil/sicp module which interacts in a strange way 4 | ; with rackets normal lists and mutable lists. 5 | ; These procedures translate values between 6 | ; the evaluator only works with expressions that are mutable lists so 7 | ; exp->mlist takes a normal expression and creates a mutable list from it 8 | #lang racket/base 9 | (require racket/mpair) 10 | (require rackunit 11 | "ex4.03.rkt") 12 | (define (exp->mlist exp) 13 | (if (pair? exp) 14 | (foldr (lambda (x rest) 15 | (if (pair? x) 16 | (mcons (exp->mlist x) rest) 17 | (mcons x rest))) 18 | null exp) 19 | exp)) 20 | (define (mlist->exp exp) 21 | (if (mlist? exp) 22 | (mlist->list exp) 23 | exp)) 24 | 25 | (define (run-interpreter exp) 26 | (mlist->exp (interpret (exp->mlist exp)))) 27 | 28 | 29 | (provide run-interpreter) -------------------------------------------------------------------------------- /Chapter4/user.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 4.41: Write an ordinary Scheme program to solve the multiple dwelling puzzle. 2 | 3 | (define (filter predicate sequence) 4 | (cond ((null? sequence) nil) 5 | ((predicate (car sequence)) 6 | (cons (car sequence) 7 | (filter predicate 8 | (cdr sequence)))) 9 | (else (filter predicate 10 | (cdr sequence))))) 11 | 12 | (define (multiple-dwelling) 13 | (let ((baker (list 1 2 3 4 5)) 14 | (cooper (list 1 2 3 4 5)) 15 | (fletcher (list 1 2 3 4 5)) 16 | (miller (list 1 2 3 4 5)) 17 | (smith (list 1 2 3 4 5))) 18 | (set! 19 | baker 20 | (filter 21 | (lambda (baker) 22 | (not (= baker 5))) 23 | baker)) 24 | (set! 25 | cooper 26 | (filter 27 | (lambda (cooper) 28 | (not (= cooper 1))) 29 | cooper)) 30 | (set! 31 | fletcher 32 | (filter 33 | (lambda (fletcher) 34 | (not (or (= fletcher 1) (= fletcher 5)))) 35 | fletcher)) 36 | (define m&c (list)) 37 | 38 | (for-each 39 | (lambda (c) 40 | (for-each 41 | (lambda (m) 42 | (if (> m c) 43 | (set! m&c (cons (list m c) m&c)) 44 | )) 45 | miller)) 46 | cooper) 47 | 48 | m&c 49 | )) 50 | (display (multiple-dwelling)) -------------------------------------------------------------------------------- /Chapter4/zamb.scm: -------------------------------------------------------------------------------- 1 | #lang swindle 2 | 3 | (define (square x) (* x x)) 4 | (define (require p) 5 | (if (not p) (amb))) 6 | (define (an-integer-between low high) 7 | (require (<= low high)) 8 | (amb low (an-integer-between (+ low 1) high))) 9 | 10 | (define (distinct? items) 11 | (cond ((null? items) true) 12 | ((null? (cdr items)) true) 13 | ((member (car items) (cdr items)) false) 14 | (else (distinct? (cdr items))))) 15 | 16 | (define (multiple-dwelling) 17 | (let ((baker (amb 1 2 3 4 5)) 18 | (cooper (amb 1 2 3 4 5)) 19 | (fletcher (amb 1 2 3 4 5)) 20 | (miller (amb 1 2 3 4 5)) 21 | (smith (amb 1 2 3 4 5))) 22 | (require 23 | (distinct? (list baker cooper fletcher 24 | miller smith))) 25 | (require (not (= baker 5))) 26 | (require (not (= cooper 1))) 27 | (require (not (= fletcher 5))) 28 | (require (not (= fletcher 1))) 29 | (require (> miller cooper)) 30 | (require 31 | (not (= (abs (- smith fletcher)) 1))) 32 | (require 33 | (not (= (abs (- fletcher cooper)) 1))) 34 | (list (list 'baker baker) 35 | (list 'cooper cooper) 36 | (list 'fletcher fletcher) 37 | (list 'miller miller) 38 | (list 'smith smith)))) 39 | (display (amb-collect (multiple-dwelling))) -------------------------------------------------------------------------------- /Chapter5/Exercise5.01.md: -------------------------------------------------------------------------------- 1 | Datapath: 2 | ![](https://github.com/soulomoon/SICP/blob/master/material/photos/5.01-data-path.jpg) 3 | 4 | controller: 5 | ![](https://github.com/soulomoon/SICP/blob/master/material/photos/5.01-controller.jpg) 6 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.02.scm: -------------------------------------------------------------------------------- 1 | ; Exercise 5.2: Use the register-machine language to describe the iterative factorial machine of Exercise 5.1. 2 | (load "/Users/soulomoon/git/SICP/Chapter5/ch5-regsim.scm") 3 | (define factorial-machine 4 | (make-machine 5 | '(c p n) 6 | (list (list '+ +) (list '* *) (list '> >)) 7 | '( 8 | (assign c (const 1)) 9 | (assign p (const 1)) 10 | test-> 11 | (test (op >) (reg c) (reg n)) 12 | (branch (label factorial-done)) 13 | (assign p (op *) (reg c) (reg p)) 14 | (assign c (op +) (reg c) (const 1)) 15 | (goto (label test->)) 16 | factorial-done 17 | ))) 18 | 19 | (define factorial-machine1 20 | (make-machine 21 | '(c p r t n) 22 | (list (list '+ +) (list '* *) (list '> >)) 23 | '( 24 | (assign c (const 1)) 25 | (assign p (const 1)) 26 | test-c 27 | (test (op >) (reg c) (reg n)) 28 | (branch (label f-done)) 29 | (assign r (op *) (reg c) (reg p)) 30 | (assign p r) 31 | (assign t (op +) (reg c) (const 1)) 32 | (assign c t) 33 | (goto (label test-c)) 34 | f-done 35 | ))) 36 | 37 | (set-register-contents! factorial-machine 'n 5) 38 | (start factorial-machine) 39 | (get-register-contents factorial-machine 'p) 40 | 41 | (set-register-contents! factorial-machine1 'n 5) 42 | (start factorial-machine1) 43 | (get-register-contents factorial-machine1 'p) 44 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.05.md: -------------------------------------------------------------------------------- 1 | Exercise 5.5: Hand-simulate the factorial and Fibonacci machines, using some nontrivial input (requiring execution of at least one recursive call). Show the contents of the stack at each significant point in the execution. 2 | factorial 3: 3 | empty 4 | ``` 5 | fact-done 6 | 7 | #------- 8 | 3 9 | fact-done 10 | 11 | #------- 12 | 2 13 | after-fact 14 | 3 15 | fact-done 16 | 17 | #------- 18 | 3 19 | fact-done 20 | 21 | #------- 22 | empty 23 | 24 | 25 | 26 | 27 | fib 2: 28 | empty 29 | 30 | #------- 31 | 2 32 | fact-done 33 | 34 | #------- 35 | 0 36 | fact-done 37 | 38 | #------- 39 | empty 40 | ``` 41 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.07.scm: -------------------------------------------------------------------------------- 1 | ;Exercise 5.7: Use the simulator to test the machines you designed in Exercise 5.4. 2 | already using it, find it in Exercise 5.4 3 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.20.md: -------------------------------------------------------------------------------- 1 | Exercise 5.20: Draw the box-and-pointer representation and the memory-vector representation (as in Figure 5.14) of the list structure produced by 2 | 3 | (define x (cons 1 2)) 4 | (define y (list x x)) 5 | with the free pointer initially p1. What is the final value of free? What pointers represent the values of x and y? 6 | box-and-pointer: 7 | ![box-and-pointer](/material/photos/5.20 box-and-pointer.jpg) 8 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.26.scm: -------------------------------------------------------------------------------- 1 | ;Exercise 5.26: Use the monitored stack to explore the tail-recursive property of the evaluator (5.4.2). Start the evaluator and define the iterative factorial procedure from 1.2.1: 2 | ; 3 | ;(define (factorial n) 4 | ; (define (iter product counter) 5 | ; (if (> counter n) 6 | ; product 7 | ; (iter (* counter product) 8 | ; (+ counter 1)))) 9 | ; (iter 1 1)) 10 | ;Run the procedure with some small values of nn. Record the maximum stack depth and the number of pushes required to compute n!n! for each of these values. 11 | ; 12 | ;You will find that the maximum depth required to evaluate n!n! is independent of nn. What is that depth? 13 | ;Determine from your data a formula in terms of nn for the total number of push operations used in evaluating n!n! for any n≥1n≥1. Note that the number of operations used is a linear function of nn and is thus determined by two constants. 14 | (load "/Users/soulomoon/git/SICP/material/allcode/load-eceval.scm") 15 | ; the total depth would be 10 16 | ; 35n + 29 17 | (i 18 | '( 19 | (define (factorial n) 20 | (define (iter product counter) 21 | (if (> counter n) 22 | product 23 | (iter (* counter product) 24 | (+ counter 1)))) 25 | (iter 1 1)) 26 | 27 | (factorial 1) 28 | (factorial 2) 29 | (factorial 3) 30 | (factorial 4) 31 | (factorial 5) 32 | )) 33 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.27.scm: -------------------------------------------------------------------------------- 1 | ;Exercise 5.27: For comparison with Exercise 5.26, explore the behavior of the following procedure for computing factorials recursively: 2 | ; 3 | ;(define (factorial n) 4 | ; (if (= n 1) 5 | ; 1 6 | ; (* (factorial (- n 1)) n))) 7 | ;By running this procedure with the monitored stack, determine, as a function of nn, the maximum depth of the stack and the total number of pushes used in evaluating n!n! for n≥1n≥1. (Again, these functions will be linear.) Summarize your experiments by filling in the following table with the appropriate expressions in terms of nn: 8 | ;RecursivefactorialIterativefactorialMaximumdepthNumber ofpushes 9 | ;MaximumNumber ofdepthpushesRecursivefactorialIterativefactorial 10 | ;The maximum depth is a measure of the amount of space used by the evaluator in carrying out the computation, and the number of pushes correlates well with the time required. 11 | (load "/Users/soulomoon/git/SICP/material/allcode/load-eceval.scm") 12 | (i 13 | '( 14 | (define (factorial n) 15 | (if (= n 1) 16 | 1 17 | (* (factorial (- n 1)) n))) 18 | 19 | 20 | (factorial 5) 21 | 22 | ) 23 | ) 24 | (maximum depth) (number of pushes) 25 | recursive 26 | factorial 3+5n 32n - 16 27 | 28 | iterative 29 | factorial 10 35n + 29 30 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.29.scm: -------------------------------------------------------------------------------- 1 | ;Exercise 5.29: Monitor the stack operations in the tree-recursive Fibonacci computation: 2 | ; 3 | ;(define (fib n) 4 | ; (if (< n 2) 5 | ; n 6 | ; (+ (fib (- n 1)) (fib (- n 2))))) 7 | ;Give a formula in terms of nn for the maximum depth of the stack required to compute Fib(n)Fib(n) for n≥2n≥2. Hint: In 1.2.2 we argued that the space used by this process grows linearly with nn. 8 | ;Give a formula for the total number of pushes used to compute Fib(n)Fib(n) for n≥2n≥2. You should find that the number of pushes (which correlates well with the time used) grows exponentially with nn. Hint: Let S(n)S(n) be the number of pushes used in computing Fib(n)Fib(n). You should be able to argue that there is a formula that expresses S(n)S(n) in terms of S(n−1)S(n−1), S(n−2)S(n−2), and some fixed “overhead” constant kk that is independent of nn. Give the formula, and say what kk is. Then show that S(n)S(n) can be expressed as a⋅Fib(n+1)+ba⋅Fib(n+1)+b and give the values of aa and bb. 9 | (load "/Users/soulomoon/git/SICP/material/allcode/load-eceval.scm") 10 | ;;;1 11 | ;maximum-depth: 5n-2 12 | ;;;2 13 | ;S(n−1)+S(n−2)+40=S(n); k = 40 14 | ;a=56 15 | ;b=-40 16 | 17 | 18 | (i 19 | '( 20 | (define (fib n) 21 | (if (< n 2) 22 | n 23 | (+ (fib (- n 1)) (fib (- n 2))))) 24 | (fib 1) 25 | (fib 2) 26 | (fib 3) 27 | (fib 4) 28 | (fib 5) 29 | (fib 6) 30 | (fib 7) 31 | (fib 8) 32 | (fib 9) 33 | )) 34 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.31.md: -------------------------------------------------------------------------------- 1 | ;Exercise 5.31: In evaluating a procedure application, the explicit-control evaluator always saves and restores the env register around the evaluation of the operator, saves and restores env around the evaluation of each operand (except the final one), saves and restores argl around the evaluation of each operand, and saves and restores proc around the evaluation of the operand sequence. For each of the following combinations, say which of these save and restore operations are superfluous and thus could be eliminated by the compiler’s preserving mechanism: 2 | ; 3 | ;(f 'x 'y) 4 | ;((f) 'x 'y) 5 | ;(f (g 'x) y) 6 | ;(f (g 'x) 'y) 7 | 8 | explicit-control interpretor way would be: 9 | operator: 10 | ```Scheme 11 | save and restore env 12 | 13 | operator(not the last): 14 | save and restore env 15 | save and restore argl 16 | save and restore proc 17 | 18 | operator(not the last): 19 | save and restore argl 20 | save and restore proc 21 | 22 | 23 | (f 'x 'y) need: 24 | none 25 | 26 | ((f) 'x 'y) need: 27 | none 28 | 29 | (f (g 'x) y) need: 30 | operator(not the last): 31 | save and restore env 32 | save and restore argl 33 | save and restore proc 34 | 35 | (f (g 'x) 'y): 36 | operator(not the last): 37 | save and restore argl 38 | save and restore proc 39 | ``` 40 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.41.scm: -------------------------------------------------------------------------------- 1 | ; 2 | ;Exercise 5.41: Write a procedure find-variable that takes as arguments a variable and a compile-time environment and returns the lexical address of the variable with respect to that environment. For example, in the program fragment that is shown above, the compile-time environment during the compilation of expression ⟨e1⟩ is ((y z) (a b c d e) (x y)). Find-variable should produce 3 | ; 4 | ;(find-variable 5 | ; 'c '((y z) (a b c d e) (x y))) 6 | ;(1 2) 7 | ; 8 | ;(find-variable 9 | ; 'x '((y z) (a b c d e) (x y))) 10 | ;(2 0) 11 | ; 12 | ;(find-variable 13 | ; 'w '((y z) (a b c d e) (x y))) 14 | (define (find-variable val env) 15 | (define (iter-var frame n) 16 | (cond 17 | ((null? frame) false) 18 | ((equal? val (car frame)) n) 19 | (else (iter-var (cdr frame) (+ n 1))))) 20 | (define (iter ev n) 21 | (if (null? ev) 22 | 'not-found 23 | ;(error "find-variable not found! :" val) 24 | (let* ((current-frame (car ev)) 25 | (tail (cdr ev)) 26 | (var-pos (iter-var current-frame 0))) 27 | (if var-pos 28 | (cons n var-pos) 29 | (iter tail (+ n 1)))))) 30 | (iter env 0)) 31 | ;(find-variable 32 | ; 'c '((y z) (a b c d e) (x y))) 33 | ;;(1 2) 34 | ; 35 | ;(find-variable 36 | ; 'x '((y z) (a b c d e) (x y))) 37 | ;;(2 0) 38 | ; 39 | ;(find-variable 40 | ; 'w '((y z) (a b c d e) (x y))) 41 | ;not-found 42 | 43 | ;Welcome to DrRacket, version 6.8 [3m]. 44 | ;Language: SICP (PLaneT 1.18); memory limit: 128 MB. 45 | ;{mcons 1 2} 46 | ;{mcons 2 0} 47 | ;'not-found 48 | ;> 49 | -------------------------------------------------------------------------------- /Chapter5/Exercise5.46.scm: -------------------------------------------------------------------------------- 1 | ;Exercise 5.46: Carry out an analysis like the one in Exercise 5.45 to determine the effectiveness of compiling the tree-recursive Fibonacci procedure 2 | ; 3 | ;(define (fib n) 4 | ; (if (< n 2) 5 | ; n 6 | ; (+ (fib (- n 1)) (fib (- n 2))))) 7 | ;compared to the effectiveness of using the special-purpose Fibonacci machine of Figure 5.12. (For measurement of the interpreted performance, see Exercise 5.29.) For Fibonacci, the time resource used is not linear in n;n; hence the ratios of stack operations will not approach a limiting value that is independent of nn. 8 | (load "/Users/soulomoon/git/SICP/Chapter5/compile-and-interpret.scm") 9 | 10 | (go-two 11 | '(define (fib n) 12 | (if (< n 2) 13 | n 14 | (+ (fib (- n 1)) (fib (- n 2))))) 15 | 16 | '( 17 | (fib 6) 18 | (fib 7) 19 | (fib 8) 20 | (fib 9) 21 | (fib 10) 22 | (define (fib n) 23 | (if (< n 2) 24 | n 25 | (+ (fib (- n 1)) (fib (- n 2))))) 26 | 27 | (fib 6) 28 | (fib 7) 29 | (fib 8) 30 | (fib 9) 31 | (fib 10) 32 | )) 33 | ; the depth is still linear to n: an + b 34 | ;interpret: a=5 35 | ;compiled: a=3 36 | ; still we get a⋅Fib(n+1)+b for all pushes 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SICP 2 | Short for the wizard book < Structure and Interpretation of Computer Programs > 3 | For better reading experience, you can find html version here: 4 | [Structure and Interpretation of Computer Programs](http://sarabander.github.io/sicp/html/index.xhtml#SEC_Contents) 5 | Here is the place I keep and display my [practices](https://github.com/soulomoon/SICP) for SICP 6 | 7 | ## Credit and resources 8 | * [Chinese Translation related](https://github.com/DeathKing/Learning-SICP) 9 | 10 | 11 | ## Environment 12 | Most of the practice done here is tested with drracket 13 | * meta header `#lang planet neil/sicp`, 14 | * some with `#lang racket` or `#lang sicp`, 15 | * if without `#lang` line, I am setting the language to SICP in the left corner (it only shows up if you have ran `#lang planet neil/sicp` before). 16 | 17 | ## All source code from the book 18 | You can find all the code from the book here 19 | [AlltheCode](https://mitpress.mit.edu/sicp/code/index.html) 20 | 21 | ## Contribution 22 | Welcome to give PRs to fix any error 23 | -------------------------------------------------------------------------------- /material/allcode/ch3support.scm: -------------------------------------------------------------------------------- 1 | ;;; CODE TO SUPPORT CHAPTER 3 OF STRUCTURE AND INTERPRETATION OF 2 | ;;; COMPUTER PROGRAMS 3 | ;;; NB. This code is *not* from the book 4 | 5 | ;;; In addition to code supplied here 6 | ;;;**For 3.4, might want parallel-execute as implemented for MIT Scheme 7 | ;;;**For 3.5, need stream special forms, which are not in Standard Scheme 8 | 9 | 10 | ;;For Section 3.1.2 -- written as suggested in footnote, 11 | ;; though the values of a, b, m may not be very "appropriately chosen" 12 | (define (rand-update x) 13 | (let ((a 27) (b 26) (m 127)) 14 | (modulo (+ (* a x) b) m))) 15 | 16 | 17 | ;;For Section 3.3.4, used by and-gate 18 | ;;Note: logical-and should test for valid signals, as logical-not does 19 | (define (logical-and x y) 20 | (if (and (= x 1) (= y 1)) 21 | 1 22 | 0)) 23 | 24 | 25 | ;;For Section 3.5 -- useful for looking at finite amounts of infinite streams 26 | ;;Print the first n elements of the stream s. 27 | ;;One version prints on one line, one on separate lines 28 | 29 | (define (print-n s n) 30 | (if (> n 0) 31 | (begin (display (stream-car s)) 32 | (display ",") 33 | (print-n (stream-cdr s) (- n 1))))) 34 | 35 | (define (print-n s n) 36 | (if (> n 0) 37 | (begin (newline) 38 | (display (stream-car s)) 39 | (print-n (stream-cdr s) (- n 1))))) 40 | 41 | 42 | ;;For Section 3.5.2, to check power series (exercises 3.59-3.62) 43 | ;;Evaluate and accumulate n terms of the series s at the given x 44 | ;;Uses horner-eval from ex 2.34 45 | (define (eval-power-series s x n) 46 | (horner-eval x (first-n-of-series s n))) 47 | (define (first-n-of-series s n) 48 | (if (= n 0) 49 | '() 50 | (cons (stream-car s) (first-n-of-series (stream-cdr s) (- n 1))))) 51 | -------------------------------------------------------------------------------- /material/allcode/load-eceval-compiler.scm: -------------------------------------------------------------------------------- 1 | ;;;; LOADS THE EXPLICIT-CONTROL EVALUATOR FROM SECTION 5.4 OF 2 | ;;;; STRUCTURE AND INTERPRETATION OF COMPUTER PROGRAMS, WITH 3 | ;;;; ALL THE SUPPORTING CODE IT NEEDS IN ORDER TO RUN. 4 | 5 | ;;;;This is like load-eceval.scm except that it loads the version 6 | ;;;; of eceval that interfaces with compiled code 7 | ;;;;It doesn't load the compiler itself -- loading the compiler is up to you. 8 | 9 | ;;;; **NB** The actual "load" calls are implementation dependent. 10 | 11 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-regsim.scm") ;reg machine simulator 12 | 13 | ;; **NB** next file contains another "load" 14 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-eceval-support.scm") ;simulation of machine operations 15 | 16 | ;;**NB** eceval-compiler *must* be loaded after eceval-support, 17 | ;; so that the version of user-print in eceval-compiler will override 18 | ;; the version in eceval-support 19 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-compiler.scm") ;eceval itself 20 | ;and interface to compiled code 21 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-eceval-compiler.scm") 22 | -------------------------------------------------------------------------------- /material/allcode/load-eceval.scm: -------------------------------------------------------------------------------- 1 | ; hack to evaluat one expression by in, or i to evaluat multible expressions 2 | 3 | ;;;; LOADS THE EXPLICIT-CONTROL EVALUATOR FROM SECTION 5.4 OF 4 | ;;;; STRUCTURE AND INTERPRETATION OF COMPUTER PROGRAMS, WITH 5 | ;;;; ALL THE SUPPORTING CODE IT NEEDS IN ORDER TO RUN. 6 | 7 | ;;;; **NB** The actual "load" calls are implementation dependent. 8 | 9 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-regsim.scm") ;reg machine simulator 10 | 11 | ;; **NB** next file contains another "load" 12 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-eceval-support.scm") ;simulation of machine operations 13 | 14 | (load "/Users/soulomoon/git/SICP/material/allcode/ch5-eceval.scm") ;eceval itself 15 | 16 | ;eval machine is: 17 | ;eceval 18 | (define (print x) (display x) (newline )) 19 | 20 | ; the register-name would be: 21 | ;(exp env val proc argl continue unev) 22 | (define (in exp) 23 | (set-register-contents! eceval 'exp exp) 24 | (start eceval) 25 | ) 26 | (define (i exps) 27 | (newline ) 28 | (newline ) 29 | (display "INTERPRETATION:") 30 | (for-each (lambda (exp) (in exp)) exps)) 31 | ;(in '(+ 1 1)) 32 | ;(i '( 33 | ; (define a 1) 34 | ; (+ a 1) 35 | ; )) 36 | 37 | ;(define (i . exp) 38 | ; (for-each (lambda ) i) 39 | ;) 40 | -------------------------------------------------------------------------------- /material/allcode/read.md: -------------------------------------------------------------------------------- 1 | All of the these code is from: 2 | [this site](https://mitpress.mit.edu/sicp/code/) 3 | -------------------------------------------------------------------------------- /material/photos/5.01-controller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/5.01-controller.jpg -------------------------------------------------------------------------------- /material/photos/5.01-data-path.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/5.01-data-path.jpg -------------------------------------------------------------------------------- /material/photos/5.03.1-controller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/5.03.1-controller.jpg -------------------------------------------------------------------------------- /material/photos/5.03.1-data-path.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/5.03.1-data-path.jpg -------------------------------------------------------------------------------- /material/photos/5.20 box-and-pointer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/5.20 box-and-pointer.jpg -------------------------------------------------------------------------------- /material/photos/Exercise 5.4 data-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soulomoon/SICP/1c6cbf5ecf6397eaeb990738a938d48c193af1bb/material/photos/Exercise 5.4 data-path.png --------------------------------------------------------------------------------