SICP/README.md
2021-04-25 08:57:17 -04:00

119 lines
5.6 KiB
Markdown

# SICP
These are my solutions to the CS classic [Structure and Interpretation of
Computer Programs](https://mitpress.mit.edu/sites/default/files/sicp/index.html).
I have looked up the answer for some exercises on the
[Scheme Community Wiki](http://community.schemewiki.org/?SICP-Solutions).
Such exercise have a mark in their respective script.
You can use the Scheme implementation by the MIT to run these scripts. In Arch,
execute `pacman -S mit-scheme` to install it. Then run the scripts via
`mit-scheme --quiet < script.scm`.
**This is currently (2021/01/25) work in progress.**
# Chapter 1
The first chapter of SICP starts by explaining the Scheme syntax. The first
couple of exercises are simple enough. However, already at 1.5, the book
foreshadows some of the difficulty that is about to come.
```scheme
(define (p) (p))
(define (test x y)
(if (= x 0) 0 y))
```
The goal is to decide whether Scheme uses applicative-order-evaluation or
normal-order-evaluation based on the above code. I have initially found the
exercise confusing, but the code triggering an infinite loop is a clear
indication of Scheme (or at least my version of Scheme, MIT Scheme) using
applicative-order-evaluation.
After this exercise, things get more comfortable again. The book proceeds to
introduce if-else clauses, conditionals, as well as recursion. The book uses
these primitives to compare iterative and recursive procedures based on a couple
of typical CS example functions such as computing Fibonacci numbers, greatest
common divisor, and fast exponentiation.
Two new insights I had how using modulo instead of subtracting the divisor
speeds up the GCD algorithm I learned in middle school and how exponentiation
can run in O(log n) by halving even exponents.
I wasn't able to prove the Golden Ration exercise at the time of working through
this chapter. My knowledge of induction and proofs was too limited. I found that
depressing at the time, and I wish they hadn't included that exercise.
Nevertheless, the book moves on to further essential CS concepts such as Prime
numbers and the Fermat primality test. Funnily enough, I used that probabilistic
Prime test for a Project Euler exercise, wondering why I wasn't able to get the
correct results. It turns out that this test detects probable primes (the book
mentions that a little later and introduces the Miller-Rabin test that
pseudoprimes cannot fool). On the one hand, it was cool to use an algorithm from
a book directly. On the other hand, I was undoubtedly a bit annoyed by that
story.
The book moves on to discuss the runtime of some of the algorithms discussed to
this point. It introduces some other mathematical concepts, such as calculating
roots via the fixed-point method, Euler expansions, and the Newton method for
finding minima/maxima. It was cool to see how the fixed-point method can be used
to implement the Newton method if you plug the derivate of a function into it. I
did my project presentation for math in high school about the Newton method. So
this brought up cool memories. I wish I still had that presentation.
Finally, SICP introduces the evaluation model for stateless functions and
concludes with some exercises that require second-order procedures: procedures
that take other procedures as arguments.
# Chapter 2
Chapter 2 starts by introducing compound data structures to represent pairs and
rational numbers. Abstraction barriers allow implementing procedures on data
types independent of the underlying representation. For example, we could reduce
a rational-number to its lowest denominator at creation or display time. The
book introduces interval arithmetic to deepen the understanding of data
abstractions.
Next, the book shows how to create more complex data structures such as lists
and trees from cons. Higher-order procedures such as map and fold operate on
these structures, for example, to update each element or to aggregate data.
The book then expands on the idea of higher-order procedures by introducing a
picture language as shown in the following image. We can manipulate a painter
with different transformations to create more complex images. The book does not
present a way to paint to the screen, so I have implemented the painter to
create a Python script that can then draw the images via the PIL library.
![Corner Split](shared/draw-corner-split-3.png)
The next section introduces symbolic data that we utilize to implement a system
for symbolic differentiation. One of my favorite things about the book is that
it references concepts from other disciplines, such as calculus. I am happy that
my high school knowledge of these topics is still present enough for me to work
through the exercises.
Next, we explore sets and different ways to present them. The section finishes
with the implementation of Huffman Encoding trees.
The rest of this chapter shows how to implement an algebra system utilizing a
data-directed programming style. We create packages for different types of
numbers, such as rational, complex, and imaginary numbers. We install methods
for all basic algebraic operations, and the functions dispatch the correct
procedure depending on the data type.
Over the next sections and many exercises, we expand the system to automatically
simplify the numbers by creating a hierarchy of data types. Eventually, we
extend the system to support polynomials and even rational polynomials by
extending our previous rational numbers implementation.
I found these exercises challenging but incredibly rewarding. The algebra system
was the point where I gave up when I worked through the book initially, so I
felt a sense of accomplishment when I finished it on my second attempt.
# Chapter 3