Skip to content

Commit

Permalink
Finish 1.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
cj1128 committed Feb 13, 2024
1 parent 3d9985e commit 0f3cd78
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 25 deletions.
199 changes: 199 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ TOC:
- [Setup](#setup)
- [Sublime Text](#sublime-text)
- [VS Code](#vs-code)
- [Chrome](#chrome)
- [Chapter 1: Building Abstractions with Procedures](#chapter-1-building-abstractions-with-procedures)
- [1.1: The Elements of Programming](#11-the-elements-of-programming)
- [1.2: Procedures and the Processes They Generate](#12-procedures-and-the-processes-they-generate)
- [Exercise](#exercise)
- [1.1](#11)
- [1.2](#12)
Expand All @@ -28,6 +30,11 @@ TOC:
- [1.6](#16)
- [1.7](#17)
- [1.8](#18)
- [1.9](#19)
- [1.10](#110)
- [1.11](#111)
- [1.12](#112)
- [1.13](#113)

## Setup

Expand Down Expand Up @@ -104,6 +111,10 @@ Add following keybinding to make it more convenient.
}
```

## Chrome

Install [Markdown Viewer](https://chromewebstore.google.com/detail/markdown-viewer/ckkdlimhmcjmikdlpkmbgfkaikojcbjk) plugin to preview this file in Chrome.

## Chapter 1: Building Abstractions with Procedures

- Lisp is so old and also so good.
Expand Down Expand Up @@ -156,6 +167,67 @@ Add following keybinding to make it more convenient.
>Lexical scoping dictates that free variables in a procedure are taken to refer to bindings made by enclosing procedure definitions; that is, they are looked up in the environment in which the procedure was defined.
> --- page39
### 1.2: Procedures and the Processes They Generate

- Recursive process::
```scheme
(define (factorial n)
(if (= n 1)
1
(* n (factorial (- n 1)))))
(factorial 6)
(* 6 (factorial 5))
(* 6 (* 5 (factorial 4)))
(* 6 (* 5 (* 4 (factorial 3))))
(* 6 (* 5 (* 4 (* 3 (factorial 2)))))
(* 6 (* 5 (* 4 (* 3 (* 2 (factorial 1))))))
(* 6 (* 5 (* 4 (* 3 (* 2 1)))))
(* 6 (* 5 (* 4 (* 3 2))))
(* 6 (* 5 (* 4 6)))
(* 6 (* 5 24))
(* 6 120)
; A linear recursion
```
>This type of process, characterized by a chain of deferred operations, is called a *recursive process*. Carrying out this process requires that the interpreter keep track of the operations to be performed later on.
> ---page 44
- Iterative process::
```scheme
(define (factorial n)
(define (fact-iter product counter max-count)
(if (> counter max-count)
product
(fact-iter (* product counter) (+ counter 1) max-count)))
(fact-iter 1 1 n))
(factorial 6)
(fact-iter 1 1 6)
(fact-iter 1 2 6)
(fact-iter 2 3 6)
(fact-iter 6 4 6)
(fact-iter 24 5 6)
(fact-iter 120 6 6)
(fact-iter 720 7 6)
```
>By contrast, the second process does not grow and shrink. At each step, all we need to keep track of, for any n, are the current values of the variables `product`, `counter`, and `max-count`. We call this an *iterative process*.
> --- page44
- The essential feature of _iterative process_ is that *its state can be summarized by a fixed number of state variables*.
>In general, an iterative process is one whose state can be summarized by a fixed number of state variables, together with a fixed rule that describes how the state variables should be updated as the process moves from state to state and an (optional) end test that specifies conditions under which the process should terminate.
> --- page44
- Pay attention that a recursive *process* is not the same as a recursive *procedure*. We can use a skill called *Tail Call Optimization* to get an iterative process of a recursive procedure.
- In my understanding, process is the running entity and procedure is the static code.
> When we describe a procedure as recursive, we are referring to the syntactic fact that the procedure definition refers (either directly or indirectly) to the procedure itself. But when we describe a process as following a pattern that is, say, linearly recursive, we are speaking about how the process evolves, not about the syntax of how a procedure is written.
> --- page45
- Calculating fibonacci is a typical *tree recursive* process
> In general, the number of steps required by a tree-recursive process will be proportional to the number of nodes in the tree, while the space required will be proportional to the maximum depth of the tree.
> --- page49
- How many different ways can we make change of $1.00, given half-dollars, quarters, dimes, nickels, and pennies?
- This problem has a simple solution as a [recursive procedure](./chapter-1/1.2/count-change.scm).
- It's not obvious how to transform this to an iterative process. I managed to come up with [one](./chapter-1/1.2/count-change-iter.scm), but I have to say it's hard to understand.
> A tree-recursive process may be highly inefficient but often easy to specify and understand
> --- page53
- We can use *memoization* to dramatically reduce time and space usage of tree-recursive process

## Exercise

### 1.1
Expand Down Expand Up @@ -230,3 +302,130 @@ Check new implementation at [1.7.scm](./chapter-1/1.1/1.7.scm)
### 1.8

[1.8.scm](./chapter-1/1.1/1.8.scm)

### 1.9

```scheme
(define (+ a b)
(if (= a 0) b (inc (+ (dec a) b))))
(+ 4 5)
;(inc (+ 3 5))
;(inc (inc (+ 2 5)))
;(inc (inc (inc (+ 1 5))))
;(inc (inc (inc (inc (+ 0 5)))))
;(inc (inc (inc (inc 5))))
;(inc (inc (inc 6)))
;(inc (inc 7))
;(inc 8)
9
; this is a recursive process.
```

```scheme
(define (+ a b)
(if (= a 0) b (+ (dec a) (inc b))))
(+ 4 5)
;(+ 3 6)
;(+ 2 7)
;(+ 1 8)
;(+ 0 9)
9
; this is an iterative process.
```

### 1.10

[1.10.scm](./chapter-1/1.2/1.10.scm)

### 1.11

The recursive version is very easy, just follow the formula.

Because this function is a slight modification of `fibonacci`, we can use the same skill to construct the iterative function.

[1.11.scm](./chapter-1/1.2/1.11.scm)

### 1.12

It's obvious that `f(row, index) = f(row-1, index-1) + f(row-1, index)`.

[1.12.scm](./chapter-1/1.2/1.12.scm)

### 1.13

Let's first prove that

$$
Fib(n) = \frac{\phi^{n} - \psi^{n}}{\sqrt{5}} \\
$$

Given

$$
\begin{gathered}
\phi = \frac{1 + \sqrt{5}}{2} \\
\psi = \frac{1 - \sqrt{5}}{2} \\
Fib(n) = Fib(n) + Fib(n-1)
\end{gathered}
$$

If

$$
\begin{align}
Fib(n) &= \frac{\phi^n - \psi^n}{\sqrt{5}} \\
Fib(n-1) &= \frac{\phi^{n-1} - \psi^{n-1}}{\sqrt{5}} \\
\end{align}
$$

Because

$$
\begin{align}
\phi\psi = -1 \\
\phi + \psi = 1 \\
\end{align}
$$

We can get

$$
\begin{align}
\phi^{n+1} - \psi^{n+1} & = \phi\phi^n - \psi\psi^{n} \\
& = (1 - \psi)\phi^n - (1 - \phi)\psi^n \\
& = \phi^n - \psi\phi^n - \psi^n + \phi\psi^n \\
& = \phi^n - \psi\phi\phi^{n-1} - \psi^n + \phi\psi\psi^{n-1} \\
& = \phi^n - \psi^n + \phi^{n-1} - \psi^{n-1} \\
\\
Fib(n+1) & = Fib(n) + Fib(n-1) \\
& = \frac{\phi^n - \psi^n + \phi^{n-1} - \psi^{n-1}}{\sqrt{5}} \\
& = \frac{\phi^{n+1} - \psi^{n+1}}{\sqrt{5}}
\end{align}
$$

To prove that $Fib(n)$ is the closest integer to $\frac{\phi^{n}}{\sqrt{5}}$, All we have to do is to prove that

$$
\begin{align}
\left| Fib(n) - \frac{\phi^n}{\sqrt{5}} \right| < \frac{1}{2} \\
\left| \frac{\phi^n}{\sqrt{5}} - \frac{\psi^n}{\sqrt{5}} - \frac{\phi^n}{\sqrt{5}} \right| < \frac{1}{2} \\
\left| \frac{\psi^n}{\sqrt{5}} \right| < \frac{1}{2} \\
\left| \frac{\psi^n}{\sqrt{5}} \right| < \frac{1}{2} \\
\left| \psi^n \right| < \frac{\sqrt{5}}{2} \\
(\frac{\sqrt{5} - 1}{2})^n < \frac{\sqrt{5}}{2}
\end{align}
$$

Because $\sqrt{5} > 2$, so all we have to prove is

$$
(\frac{\sqrt{5} - 1}{2})^n <= 1
$$

Because $0 < \frac{\sqrt{5} - 1}{2} < 1$, so based on the properties of exponential functions, the above is true.
23 changes: 10 additions & 13 deletions chapter-1/1.2/1.12.scm
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@
(f (- r 1) i)
(f (- r 1) (- i 1))))))

(display (f 5 1))
(newline)
; row: 1-based
(define (print-row row)
(define (iter cur)
(if (<= cur row)
(begin
(display (f row cur))
(display " ")
(iter (+ cur 1)))))
(iter 1))

(display (f 5 2))
(newline)

(display (f 5 3))
(newline)

(display (f 5 4))
(newline)

(display (f 5 5))
(newline)
(print-row 5)
11 changes: 7 additions & 4 deletions chapter-1/1.2/count-change-iter.scm
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@
((> (* half-dollar 50) amount) ways) ; stop
((> (+
(* half-dollar 50)
(* quarter 25)) amount)
(* quarter 25))
amount)
(iter ways (+ 1 half-dollar) 0 0 0))
((> (+
(* half-dollar 50)
(* quarter 25)
(* dime 10)) amount)
(* dime 10))
amount)
(iter ways half-dollar (+ 1 quarter) 0 0))
((> (+
(* half-dollar 50)
(* quarter 25)
(* dime 10)
(* nickle 5)) amount)
(* nickle 5))
amount)
(iter ways half-dollar quarter (+ 1 dime) 0))
(else (iter (+ 1 ways) half-dollar quarter dime (+ 1 nickle)))))
(iter 0 0 0 0 0))

(display (count-change 60))
(display (count-change 6))
16 changes: 8 additions & 8 deletions chapter-1/1.2/count-change.scm
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
; if kind-of-coins is 0, we should count that as 0 ways to make change

(define (count-change target)
; 50, 25, 10, 5, 1
(define (first-denomination k)
(cond
((= k 5) 50)
((= k 4) 25)
((= k 3) 10)
((= k 2) 5)
((= k 1) 1)))
(define (cc amount kind-of-coins)
; 50, 25, 10, 5, 1
(define (first-denomination k)
(cond
((= k 5) 50)
((= k 4) 25)
((= k 3) 10)
((= k 2) 5)
((= k 1) 1)))
(cond
((= amount 0) 1)
((< amount 0) 0)
Expand Down

0 comments on commit 0f3cd78

Please sign in to comment.