<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>欲說還休</title><link>https://blog.terryx.com/tags/sicp/</link><description>TerryX's Blog</description><generator>Hugo 0.161.1</generator><language>zh-cn</language><managingEditor>TerryX</managingEditor><lastBuildDate>Wed, 21 Mar 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.terryx.com/tags/sicp/index.xml" rel="self" type="application/rss+xml"/><item><title>Hierarchical Data and the Closure Property</title><link>https://blog.terryx.com/posts/sicp-2-2/</link><pubDate>Mon, 02 Jan 2017 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-2-2/</guid><description><![CDATA[<h2 id="section-22--hierarchical-data-and-the-closure-property">Section 2.2  Hierarchical Data and the Closure Property</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 2.17.</strong>  Define a procedure <code>last-pair</code> that returns the list that contains only the last element of a given (nonempty) list:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(last-pair (list 23 72 149 34))
</span></span><span class="line"><span class="cl">(34)
</span></span></code></pre></div><p><strong>Answer 2.17.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (last-pair items)
</span></span><span class="line"><span class="cl">    (if (null? (cdr items))
</span></span><span class="line"><span class="cl">        items
</span></span><span class="line"><span class="cl">        (last-pair (cdr items))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.18.</strong>  Define a procedure <code>reverse</code> that takes a list as argument and returns a list of the same elements in reverse order:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(reverse (list 1 4 9 16 25))
</span></span><span class="line"><span class="cl">(25 16 9 4 1)
</span></span></code></pre></div><p><strong>Answer 2.18.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (reverse items)
</span></span><span class="line"><span class="cl">    (if (null? (cdr items))
</span></span><span class="line"><span class="cl">        items
</span></span><span class="line"><span class="cl">        (append (reverse (cdr items)) (cons (car items) ()))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.19.</strong>  Consider the change-counting program of section 1.2.2. It would be nice to be able to easily change the currency used by the program, so that we could compute the number of ways to change a British pound, for example. As the program is written, the knowledge of the currency is distributed partly into the procedure <code>first-denomination</code> and partly into the procedure <code>count-change</code> (which knows that there are five kinds of U.S. coins). It would be nicer to be able to supply a list of coins to be used for making change.</p>
<p>We want to rewrite the procedure cc so that its second argument is a list of the values of the coins to use rather than an integer specifying which coins to use. We could then have lists that defined each kind of currency:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define us-coins (list 50 25 10 5 1))
</span></span><span class="line"><span class="cl">(define uk-coins (list 100 50 20 10 5 2 1 0.5))
</span></span></code></pre></div><p>We could then call cc as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cc 100 us-coins)
</span></span><span class="line"><span class="cl">292
</span></span></code></pre></div><p>To do this will require changing the program <code>cc</code> somewhat. It will still have the same form, but it will access its second argument differently, as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cc amount coin-values)
</span></span><span class="line"><span class="cl">  (cond ((= amount 0) 1)
</span></span><span class="line"><span class="cl">        ((or (&lt; amount 0) (no-more? coin-values)) 0)
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (+ (cc amount
</span></span><span class="line"><span class="cl">                (except-first-denomination coin-values))
</span></span><span class="line"><span class="cl">            (cc (- amount
</span></span><span class="line"><span class="cl">                   (first-denomination coin-values))
</span></span><span class="line"><span class="cl">                coin-values)))))
</span></span></code></pre></div><p>Define the procedures <code>first-denomination</code>, <code>except-first-denomination</code>, and <code>no-more?</code> in terms of primitive operations on list structures. Does the order of the list <code>coin-values</code> affect the answer produced by <code>cc</code>? Why or why not?</p>
<p><strong>Answer 2.19.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cc amount coin-values)
</span></span><span class="line"><span class="cl">  (cond ((= amount 0) 1)
</span></span><span class="line"><span class="cl">        ((or (&lt; amount 0) (no-more? coin-values)) 0)
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (+ (cc amount
</span></span><span class="line"><span class="cl">                (except-first-denomination coin-values))
</span></span><span class="line"><span class="cl">            (cc (- amount
</span></span><span class="line"><span class="cl">                   (first-denomination coin-values))
</span></span><span class="line"><span class="cl">                coin-values)))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (no-more? coin-values)
</span></span><span class="line"><span class="cl">    (null? coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (except-first-denomination coin-values)
</span></span><span class="line"><span class="cl">    (cdr coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (first-denomination coin-values)
</span></span><span class="line"><span class="cl">    (car coin-values)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define us-coins (list 50 25 10 5 1))
</span></span><span class="line"><span class="cl">(define uk-coins (list 100 50 20 10 5 2 1 0.5))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(cc 100 us-coins)
</span></span></code></pre></div><p><strong>Exercise 2.20.</strong>  The procedures <code>+</code>, <code>*</code>, and list take arbitrary numbers of arguments. One way to define such procedures is to use define with <em>dotted-tail notation</em>. In a procedure definition, a parameter list that has a dot before the last parameter name indicates that, when the procedure is called, the initial parameters (if any) will have as values the initial arguments, as usual, but the final parameter’s value will be a <em>list</em> of any remaining arguments. For instance, given the definition</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f x y . z) &lt;body&gt;)
</span></span></code></pre></div><p>the procedure <code>f</code> can be called with two or more arguments. If we evaluate</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(f 1 2 3 4 5 6)
</span></span></code></pre></div><p>then in the body of <code>f</code>, <code>x</code> will be $1$, <code>y</code> will be $2$, and <code>z</code> will be the list <code>(3 4 5 6)</code>. Given the definition</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (g . w) &lt;body&gt;)
</span></span></code></pre></div><p>the procedure <code>g</code> can be called with zero or more arguments. If we evaluate</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(g 1 2 3 4 5 6)
</span></span></code></pre></div><p>then in the body of <code>g</code>, <code>w</code> will be the list <code>(1 2 3 4 5 6)</code>.</p>
<p>Use this notation to write a procedure <code>same-parity</code> that takes one or more integers and returns a list of all the arguments that have the same even-odd parity as the first argument. For example,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(same-parity 1 2 3 4 5 6 7)
</span></span><span class="line"><span class="cl">(1 3 5 7)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(same-parity 2 3 4 5 6 7)
</span></span><span class="line"><span class="cl">(2 4 6)
</span></span></code></pre></div><p><strong>Answer 2.20.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (same-parity first . rest)
</span></span><span class="line"><span class="cl">    (define (filter x)
</span></span><span class="line"><span class="cl">        (if (even? x)
</span></span><span class="line"><span class="cl">            even?
</span></span><span class="line"><span class="cl">            odd?
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (parity f l)
</span></span><span class="line"><span class="cl">        (cond ((null? l) ())
</span></span><span class="line"><span class="cl">              ((f (car l)) (cons (car l) (parity f (cdr l))))
</span></span><span class="line"><span class="cl">              (else (parity f (cdr l)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (parity (filter first) rest)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.21.</strong>  The procedure <code>square-list</code> takes a list of numbers as argument and returns a list of the squares of those numbers.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(square-list (list 1 2 3 4))
</span></span><span class="line"><span class="cl">(1 4 9 16)
</span></span></code></pre></div><p>Here are two different definitions of <code>square-list</code>. Complete both of them by filling in the missing expressions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (if (null? items)
</span></span><span class="line"><span class="cl">      nil
</span></span><span class="line"><span class="cl">      (cons &lt;??&gt; &lt;??&gt;)))
</span></span><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (map &lt;??&gt; &lt;??&gt;))
</span></span></code></pre></div><p><strong>Answer 2.21.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">    (if (null? items)
</span></span><span class="line"><span class="cl">        `()
</span></span><span class="line"><span class="cl">        (cons (square (car items)) (square-list (cdr items)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x) (* x x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square-list-map items)
</span></span><span class="line"><span class="cl">    (map square items)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.22.</strong>  Louis Reasoner tries to rewrite the first <code>square-list</code> procedure of exercise 2.21 so that it evolves an iterative process:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (define (iter things answer)
</span></span><span class="line"><span class="cl">    (if (null? things)
</span></span><span class="line"><span class="cl">        answer
</span></span><span class="line"><span class="cl">        (iter (cdr things) 
</span></span><span class="line"><span class="cl">              (cons (square (car things))
</span></span><span class="line"><span class="cl">                    answer))))
</span></span><span class="line"><span class="cl">  (iter items nil))
</span></span></code></pre></div><p>Unfortunately, defining square-list this way produces the answer list in the reverse order of the one desired. Why?</p>
<p>Louis then tries to fix his bug by interchanging the arguments to <code>cons</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square-list items)
</span></span><span class="line"><span class="cl">  (define (iter things answer)
</span></span><span class="line"><span class="cl">    (if (null? things)
</span></span><span class="line"><span class="cl">        answer
</span></span><span class="line"><span class="cl">        (iter (cdr things)
</span></span><span class="line"><span class="cl">              (cons answer
</span></span><span class="line"><span class="cl">                    (square (car things))))))
</span></span><span class="line"><span class="cl">  (iter items nil))
</span></span></code></pre></div><p>This doesn’t work either. Explain.</p>
<p><strong>Answer 2.22.</strong> The first procedure doesn’t work because it constructs the last item from the front of the list to the answer. The second procedure seems right at first glance, but result is:</p>
<p><code>(square-list (list 1 2 3 4)) ((((() 1) 4) 9) 16)</code></p>
<p>Let’s look the definition of <code>list</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(list &lt;a_1&gt; &lt;a_2&gt; ... &lt;a_n&gt;)
</span></span><span class="line"><span class="cl">(cons &lt;a_1&gt; (cons &lt;a_2&gt; ... (cons &lt;a_n&gt; nil) ... ))
</span></span></code></pre></div><p>And the substitution of the procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(square-list (list 1 2 3 4))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 1 2 3 4) &#39;())
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 2 3 4) (cons &#39;() (square 1)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 3 4) (cons (cons &#39;() 1)
</span></span><span class="line"><span class="cl">                       (square 2)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter (list 4)  (cons (cons (cons &#39;() 1) 4)
</span></span><span class="line"><span class="cl">                      (square 3)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter &#39;() (cons (cons (cons (cons &#39;() 1) 4) 9)
</span></span><span class="line"><span class="cl">                (square 4)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(iter &#39;() (cons (cons (cons (cons &#39;() 1) 4) 9) 16))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(cons (cons (cons (cons &#39;() 1) 4) 9) 16)
</span></span></code></pre></div><p>Therefore, the structure of answer is wrong.</p>
<p><strong>Exercise 2.23.</strong>  The procedure <code>for-each</code> is similar to <code>map</code>. It takes as arguments a procedure and a list of elements. However, rather than forming a list of the results, <code>for-each</code> 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 – <code>for-each</code> is used with procedures that perform an action, such as printing. For example,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(for-each (lambda (x) (newline) (display x))
</span></span><span class="line"><span class="cl">          (list 57 321 88))
</span></span><span class="line"><span class="cl">57
</span></span><span class="line"><span class="cl">321
</span></span><span class="line"><span class="cl">88
</span></span></code></pre></div><p>The value returned by the call to <code>for-each</code> (not illustrated above) can be something arbitrary, such as true. Give an implementation of <code>for-each</code>.</p>
<p><strong>Answer 2.23.</strong>  I find a feature between <code>cond</code> and <code>if</code> in Lisp. If we want to use <code>if</code> instead of <code>cond</code>, one things should be concerned. Here are definitions:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cond (&lt;predicate&gt; &lt;expression&gt; ...)
</span></span><span class="line"><span class="cl">	  ...
</span></span><span class="line"><span class="cl">	  (else &lt;expression&gt; ..)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(if &lt;predicate&gt;
</span></span><span class="line"><span class="cl">	&lt;consequent&gt;
</span></span><span class="line"><span class="cl">	&lt;alternative&gt;
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>In <code>cond</code>, one clause has one predicate and several expressions, meanwhile consequent and alternative of <code>if</code> only have one expression for each. Thus, in this exercise we should use <code>cond</code> because <code>(newline)</code> and <code>(display x)</code> are two expressions.</p>
<pre tabindex="0"><code>(define (for-each f l)
    (cond ((null? l) &#39;()) 
          (else (f (car l))
                (for-each f (cdr l)))
    )
)
</code></pre><p><strong>Exercise 2.24.</strong>  Suppose we evaluate the expression <code>(list 1 (list 2 (list 3 4)))</code>. 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).</p>
]]></description></item><item><title>Introduction to Data Abstraction</title><link>https://blog.terryx.com/posts/sicp-2-1/</link><pubDate>Sat, 31 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-2-1/</guid><description><![CDATA[<h2 id="section-21--introduction-to-data-abstraction">Section 2.1  Introduction to Data Abstraction</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 2.1.</strong>  Define a better version of <code>make-rat</code> that handles both positive and negative arguments. <code>Make-rat</code> 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.</p>
<p><strong>Answer 2.1.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (numer x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (denom x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-rat x)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display (numer x))
</span></span><span class="line"><span class="cl">    (display &#34;/&#34;)
</span></span><span class="line"><span class="cl">    (display (denom x))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-rat n d)
</span></span><span class="line"><span class="cl">    (let ((g ((if (&lt; d 0) - +) (abs (gcd n d)))))
</span></span><span class="line"><span class="cl">        (cons (/ n g) (/ d g))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.2.</strong>  Consider the problem of representing line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor <code>make-segment</code> and selectors <code>start-segment</code> and <code>end-segment</code> that define the representation of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the $x$ coordinate and the $y$ coordinate. Accordingly, specify a constructor <code>make-point</code> and selectors <code>x-point</code> and <code>y-point</code> that define this representation. Finally, using your selectors and constructors, define a procedure <code>midpoint-segment</code> that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints). To try your procedures, you’ll need a way to print points:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">  (display (x-point p))
</span></span><span class="line"><span class="cl">  (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">  (display (y-point p))
</span></span><span class="line"><span class="cl">  (display &#34;)&#34;))
</span></span></code></pre></div><p><strong>Answer 2.2.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (x-point x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (y-point x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">    (display (x-point p))
</span></span><span class="line"><span class="cl">    (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">    (display (y-point p))
</span></span><span class="line"><span class="cl">    (display &#34;)&#34;)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-point x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (start-segment x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (end-segment x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-segment x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (midpoint-segment s)
</span></span><span class="line"><span class="cl">    (define (average a b) (/ (+ a b) 2.0))
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (a (start-segment s))
</span></span><span class="line"><span class="cl">            (b (end-segment s))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (make-point (average (x-point a) (x-point b)) (average (y-point a) (y-point b)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.3.</strong>  Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles. Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work using either representation?</p>
<p><strong>Answer 2.3.</strong> Here, it talks about axis-aligned rectangles.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (x-point x) (car x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (y-point x) (cdr x))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-point p)
</span></span><span class="line"><span class="cl">    (newline)
</span></span><span class="line"><span class="cl">    (display &#34;(&#34;)
</span></span><span class="line"><span class="cl">    (display (x-point p))
</span></span><span class="line"><span class="cl">    (display &#34;,&#34;)
</span></span><span class="line"><span class="cl">    (display (y-point p))
</span></span><span class="line"><span class="cl">    (display &#34;)&#34;)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-point x y)
</span></span><span class="line"><span class="cl">    (cons x y)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (make-rect p1 p2)
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (x1 (x-point p1))
</span></span><span class="line"><span class="cl">            (x2 (x-point p2))
</span></span><span class="line"><span class="cl">            (y1 (y-point p1))
</span></span><span class="line"><span class="cl">            (y2 (y-point p2))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (cond 
</span></span><span class="line"><span class="cl">            ((and (&lt; x1 x2) (&lt; y1 y2)) (cons p1 p2))
</span></span><span class="line"><span class="cl">            ((and (&gt; x1 x2) (&gt; y1 y2)) (cons p2 p1))
</span></span><span class="line"><span class="cl">            ((and (&lt; x1 x2) (&gt; y1 y2)) (cons (make-point (x1 y2)) (make-point (x2 y1))))
</span></span><span class="line"><span class="cl">            (else (cons (make-point (x2 y1)) (make-point (x1 y2))))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (bottom-left r) (car r))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (top-right r) (cdr r))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (print-rect r)
</span></span><span class="line"><span class="cl">    (print-point (bottom-left r))
</span></span><span class="line"><span class="cl">    (print-point (top-right r))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (perimeter r)
</span></span><span class="line"><span class="cl">    (let (
</span></span><span class="line"><span class="cl">            (p1 (bottom-left r))
</span></span><span class="line"><span class="cl">            (p2 (top-right r))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (let (
</span></span><span class="line"><span class="cl">                (x1 (x-point p1))
</span></span><span class="line"><span class="cl">                (x2 (x-point p2))
</span></span><span class="line"><span class="cl">                (y1 (y-point p1))
</span></span><span class="line"><span class="cl">                (y2 (y-point p2))
</span></span><span class="line"><span class="cl">              )
</span></span><span class="line"><span class="cl">              (* 2 (+ (- x2 x1) (- y2 y1)))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )    
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (area r)
</span></span><span class="line"><span class="cl">     (let (
</span></span><span class="line"><span class="cl">            (p1 (bottom-left r))
</span></span><span class="line"><span class="cl">            (p2 (top-right r))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">         (let (
</span></span><span class="line"><span class="cl">                (x1 (x-point p1))
</span></span><span class="line"><span class="cl">                (x2 (x-point p2))
</span></span><span class="line"><span class="cl">                (y1 (y-point p1))
</span></span><span class="line"><span class="cl">                (y2 (y-point p2))
</span></span><span class="line"><span class="cl">              )
</span></span><span class="line"><span class="cl">              (* (- x2 x1) (- y2 y1))
</span></span><span class="line"><span class="cl">         )
</span></span><span class="line"><span class="cl">    )    
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define r (make-rect (make-point 1 1)
</span></span><span class="line"><span class="cl">                     (make-point 4 5)))
</span></span></code></pre></div><p><strong>Exercise 2.4.</strong>  Here is an alternative procedural representation of pairs. For this representation, verify that <code>(car (cons x y))</code> yields $x$ for any objects $x$ and $y$.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cons x y)
</span></span><span class="line"><span class="cl">  (lambda (m) (m x y)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (car z)
</span></span><span class="line"><span class="cl">  (z (lambda (p q) p)))
</span></span></code></pre></div><p>What is the corresponding definition of <code>cdr</code>? (Hint: To verify that this works, make use of the substitution model of section 1.1.5.)</p>
<p><strong>Answer 2.4.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cdr z)
</span></span><span class="line"><span class="cl">	(z (lambda (p q) q))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>Substitution model:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (cdr z)
</span></span><span class="line"><span class="cl">=&gt; (z (lambda (p q) p))
</span></span><span class="line"><span class="cl">=&gt; ((lambda (m) (m x y) (lambda (p q) q)))
</span></span><span class="line"><span class="cl">=&gt; ((lambda (p q) q) x y)
</span></span><span class="line"><span class="cl">=&gt; y
</span></span></code></pre></div><p><strong>Exercise 2.5.</strong>  Show that we can represent pairs of nonnegative integers using only numbers and arithmetic operations if we represent the pair $a$ and $b$ as the integer that is the product $2^a 3^b$. Give the corresponding definitions of the procedures <code>cons</code>, <code>car</code>, and <code>cdr</code>.</p>
<p><strong>Answer 2.5.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cons a b)
</span></span><span class="line"><span class="cl">    (* (expt 2 a) (expt 3 b))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (logb b n) (floor (/ (log n) (log b))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (car x)
</span></span><span class="line"><span class="cl">    (logb 2 (/ x (gcd x (expt 3 (logb 3 x)))))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cdr x)
</span></span><span class="line"><span class="cl">    (logb 3 (/ x (gcd x (expt 2 (logb 2 x)))))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.6.</strong>  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</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define zero (lambda (f) (lambda (x) x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (add-1 n)
</span></span><span class="line"><span class="cl">  (lambda (f) (lambda (x) (f ((n f) x)))))
</span></span></code></pre></div><p>This representation is known as <em>Church numerals</em>, after its inventor, Alonzo Church, the logician who invented the $\lambda$ calculus.</p>
<p>Define <code>one</code> and <code>two</code> directly (not in terms of <code>zero</code> and <code>add-1</code>). (Hint: Use substitution to evaluate (<code>add-1 zero</code>)). Give a direct definition of the addition procedure <code>+</code> (not in terms of repeated application of <code>add-1</code>).</p>
<p><strong>Answer 2.6.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (one)
</span></span><span class="line"><span class="cl">=&gt; (add-1 zero)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f ((zero f) x))))
</span></span></code></pre></div><p><code>zero</code> is a function of one argument, that returns a function of one argument that returns the argument.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; ((zero f) x)
</span></span><span class="line"><span class="cl">=&gt; ((lambda(x) x) x)
</span></span><span class="line"><span class="cl">=&gt; x
</span></span></code></pre></div><p>So, <code>one</code> and <code>two</code> are:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (one)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">=&gt; (two)
</span></span><span class="line"><span class="cl">=&gt; (add-1 two)
</span></span><span class="line"><span class="cl">=&gt; (lambda (f) (lambda (x) (f (f x))))
</span></span></code></pre></div><p>Thus,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define one (lambda (f) (lambda (x) (f x))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define two (lambda (f) (lambda (x) (f (f x)))))
</span></span></code></pre></div><p>And <code>add</code> using the same approach in <code>add-1</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (add a b)
</span></span><span class="line"><span class="cl">	(lambda (f)
</span></span><span class="line"><span class="cl">		(lambda (x) (a f) ((b f) x))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.7.</strong>  Alyssa’s program is incomplete because she has not specified the implementation of the interval abstraction. Here is a definition of the interval constructor:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (make-interval a b) (cons a b))
</span></span></code></pre></div><p>Define selectors <code>upper-bound</code> and <code>lower-bound</code> to complete the implementation.</p>
<p><strong>Answer 2.7.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (upper-bound interval)
</span></span><span class="line"><span class="cl">	(max (car interval) (cdr interval))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (lower-bound interval)
</span></span><span class="line"><span class="cl">	(min (car interval) (cdr interval))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.8.</strong>  Using reasoning analogous to Alyssa’s, describe how the difference of two intervals may be computed. Define a corresponding subtraction procedure, called <code>sub-interval</code>.</p>
<p><strong>Answer 2.8.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sub-interval x y)
</span></span><span class="line"><span class="cl">	(make-interval (- (lower-bound x) (upper-bound y))
</span></span><span class="line"><span class="cl">				   (- (upper-bound x) (lower-bound y)))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.9.</strong>  The <em>width</em> of an interval is half of the difference between its upper and lower bounds. The width is a measure of the uncertainty of the number specified by the interval. For some arithmetic operations the width of the result of combining two intervals is a function only of the widths of the argument intervals, whereas for others the width of the combination is not a function of the widths of the argument intervals. Show that the width of the sum (or difference) of two intervals is a function only of the widths of the intervals being added (or subtracted). Give examples to show that this is not true for multiplication or division.</p>
<p><strong>Answer 2.9.</strong> For multiplication and division, the story is different. If the width of the result was a function of the widths of the inputs, then multiplying different intervals with the same widths should give the same answer. For example, multiplying a width 5 interval with a width 1 interval.</p>
<p><strong>Exercise 2.10.</strong>  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.</p>
<p><strong>Answer 2.10.</strong> We should guarantee:</p>
<p>$$
R_p = \frac{1}{1/R_1+1/R_2} = \frac{R_1+R_2}{R_1 R_2}, \text{where } R_1 R_2 \neq 0.
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (div-interval x y)
</span></span><span class="line"><span class="cl">	(if (&gt;= 0 (* (lower-bound y) (upper-bound y)))
</span></span><span class="line"><span class="cl">		(error &#34;Divison 0 error&#34;)
</span></span><span class="line"><span class="cl">		(mul-interval x (make-interval (/ 1 (upper-bound y))
</span></span><span class="line"><span class="cl">							(/ 1 (lower-bound y))
</span></span><span class="line"><span class="cl">						))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 2.11.</strong>  In passing, Ben also cryptically comments: “By testing the signs of the endpoints of the intervals, it is possible to break <code>mul-interval</code> into nine cases, only one of which requires more than two multiplications.” Rewrite this procedure using Ben’s suggestion.</p>
<p>After debugging her program, Alyssa shows it to a potential user, who complains that her program solves the wrong problem. He wants a program that can deal with numbers represented as a center value and an additive tolerance; for example, he wants to work with intervals such as $3.5 \pm 0.15$ rather than $[3.35, 3.65]$. Alyssa returns to her desk and fixes this problem by supplying an alternate constructor and alternate selectors:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (make-center-width c w)
</span></span><span class="line"><span class="cl">  (make-interval (- c w) (+ c w)))
</span></span><span class="line"><span class="cl">(define (center i)
</span></span><span class="line"><span class="cl">  (/ (+ (lower-bound i) (upper-bound i)) 2))
</span></span><span class="line"><span class="cl">(define (width i)
</span></span><span class="line"><span class="cl">  (/ (- (upper-bound i) (lower-bound i)) 2))
</span></span></code></pre></div><p>Unfortunately, most of Alyssa’s users are engineers. Real engineering situations usually involve measurements with only a small uncertainty, measured as the ratio of the width of the interval to the midpoint of the interval. Engineers usually specify percentage tolerances on the parameters of devices, as in the resistor specifications given earlier.</p>
]]></description></item><item><title>Formulating Abstractions with Higher-Order Procedures</title><link>https://blog.terryx.com/posts/sicp-1-3/</link><pubDate>Sun, 25 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-1-3/</guid><description><![CDATA[<h2 id="section-13-formulating-abstractions-with-higher-order-procedures">Section 1.3 Formulating Abstractions with Higher-Order Procedures</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>, and Merry Xmas.</p>
<p><strong>Exercise 1.29.</strong>  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 $f$ between $a$ and $b$ is approximated as</p>
<p>$$
\frac{h}{3}[y_0+4y_1+2y_2+4y_3+…+2y_{n-2}+4y_{n-1}+y_n]
$$</p>
<p>where $h = (b - a)/n$, for some even integer $n$, and $y_k = f(a + kh)$. (Increasing $n$ increases the accuracy of the approximation.) Define a procedure that takes as arguments $f$, $a$, $b$, and $n$ and returns the value of the integral, computed using Simpson’s Rule. Use your procedure to integrate cube between $0$ and $1$ (with $n = 100$ and $n = 1000$), and compare the results to those of the integral procedure shown above.</p>
<p><strong>Answer 1.29.</strong> The Simpson’s Rule can also be written as follow:</p>
<p>$$
\frac{h}{3}[y_0+4y_1+2y_2+4y_3+…+2y_{n-2}+4y_{n-1}+y_n] = \frac{h}{3}\sum_{j=2,4…}^{n}[y_{j-2} + 4y_{j-1} + y_{j}]
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        0
</span></span><span class="line"><span class="cl">        (+ (term a)
</span></span><span class="line"><span class="cl">           (sum term (next a) next b)
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (simpson-rule f a b n)
</span></span><span class="line"><span class="cl">    (define (simpson-next x)
</span></span><span class="line"><span class="cl">        (+ x 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    (define h (/ (- b a) n))
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    (define (y k)
</span></span><span class="line"><span class="cl">        (f (+ a (* k h)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (simpson-term x)
</span></span><span class="line"><span class="cl">        (+
</span></span><span class="line"><span class="cl">            (y x)
</span></span><span class="line"><span class="cl">            (* 4 (y (+ x 1)))
</span></span><span class="line"><span class="cl">            (y (+ x 2))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (* (sum simpson-term 0 simpson-next n ) (/ h 3))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cub x)
</span></span><span class="line"><span class="cl">    (* x x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(simpson-rule cub 0 1 100))
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(simpson-rule cub 0 1 1000))
</span></span></code></pre></div><p><strong>Exercise 1.30.</strong>  The <code>sum</code> 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:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">  (define (iter a result)
</span></span><span class="line"><span class="cl">      (if &lt;??&gt;
</span></span><span class="line"><span class="cl">	      &lt;??&gt;
</span></span><span class="line"><span class="cl">		  (iter &lt;??&gt; &lt;??&gt;))
</span></span><span class="line"><span class="cl">  (iter &lt;??&gt; &lt;??&gt;)
</span></span></code></pre></div><p><strong>Answer 1.30.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">	(define (iter a result)
</span></span><span class="line"><span class="cl">		(if (&gt; a b)
</span></span><span class="line"><span class="cl">			result
</span></span><span class="line"><span class="cl">			(iter (next a) (+ result (term a)))
</span></span><span class="line"><span class="cl">		)
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">	(iter a 0)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.31.</strong></p>
<p>a.  The <code>sum</code> procedure is only the simplest of a vast number of similar abstractions that can be captured as higher-order procedures. Write an analogous procedure called <code>product</code> that returns the product of the values of a function at points over a given range. Show how to define <code>factorial</code> in terms of product. Also use product to compute approximations to $\pi$ using the formula</p>
<p>$$
\frac{\pi}{4}=\frac{2 \cdot 4 \cdot 4 \cdot 6 \cdot 6 \cdot 8 …}{3 \cdot 3 \cdot 5 \cdot 5 \cdot 7 \cdot 7 …}
$$</p>
<p>b.  If your product procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.31.</strong></p>
<p>$$
\frac{\pi}{4}=\frac{2 \cdot 4 \cdot 4 \cdot 6 \cdot 6 \cdot 8 …}{3 \cdot 3 \cdot 5 \cdot 5 \cdot 7 \cdot 7 …} =
\frac{1}{n+1}\prod_{i=1}^{n}[(\frac{2(i+1)}{2i})^2]
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        1
</span></span><span class="line"><span class="cl">        (* (term a) (product term (next a) next b))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (factorial n)
</span></span><span class="line"><span class="cl">    (define (identity x)
</span></span><span class="line"><span class="cl">        x
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (define (next x)
</span></span><span class="line"><span class="cl">        (+ x 1)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (product identity 1 next n)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (define (iter a result)
</span></span><span class="line"><span class="cl">        (if (&gt; a b)
</span></span><span class="line"><span class="cl">            result
</span></span><span class="line"><span class="cl">            (iter (next a) (* result (term a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (iter a 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (pi-product a b)
</span></span><span class="line"><span class="cl">    (define (pi-term x)
</span></span><span class="line"><span class="cl">       (square (/ (* 2 (+ x 1)) (+ (* 2 x) 1)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (define (pi-next x)
</span></span><span class="line"><span class="cl">        (+ x 1)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (* 4 (/ (product-iter pi-term a pi-next b) (+ b 1)))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(exact-&gt;inexact(pi-product 1 10000))
</span></span></code></pre></div><p><strong>Exercise 1.32.</strong></p>
<p>a. Show that <code>sum</code> and <code>product</code> (exercise 1.31) are both special cases of a still more general notion called <code>accumulate</code> that combines a collection of terms, using some general accumulation function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(accumulate combiner null-value term a next b)
</span></span></code></pre></div><p><code>Accumulate</code> takes as arguments the same term and range specifications as <code>sum</code> and <code>product</code>, together with a <code>combiner</code> procedure (of two arguments) that specifies how the current term is to be combined with the accumulation of the preceding terms and a <code>null-value</code> that specifies what base value to use when the terms run out. Write <code>accumulate</code> and show how <code>sum</code> and <code>product</code> can both be defined as simple calls to <code>accumulate</code>.</p>
<p>b. If your <code>accumulate</code> procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.32.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (accumulate combiner null-value term a next b)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        null-value
</span></span><span class="line"><span class="cl">        (combiner (term a) (accumulate combiner null-value term (next a) next b))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (accumlate-iter combiner null-value term a next b)
</span></span><span class="line"><span class="cl">    (define (iter a result)
</span></span><span class="line"><span class="cl">        (if (&gt; a b) res
</span></span><span class="line"><span class="cl">            (iter (next a) (combiner res (term a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (iter a null-value)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sum term a next b)
</span></span><span class="line"><span class="cl">    (accumulate + 0 term a next b)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (product term a next b)
</span></span><span class="line"><span class="cl">    (accumlate * 1 term a next b)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.33.</strong>  You can obtain an even more general version of <code>accumulate</code> (exercise 1.32) by introducing the notion of a <em>filter</em> on the terms to be combined. That is, combine only those terms derived from values in the range that satisfy a specified condition. The resulting <code>filtered-accumulate</code> abstraction takes the same arguments as accumulate, together with an additional predicate of one argument that specifies the filter. Write <code>filtered-accumulate</code> as a procedure. Show how to express the following using <code>filtered-accumulate</code>:</p>
<p>a. the sum of the squares of the prime numbers in the interval $a$ to $b$ (assuming that you have a <code>prime</code>? predicate already written)</p>
<p>b. the product of all the positive integers less than $n$ that are relatively prime to $n$ (i.e., all positive integers $i &lt; n$ such that $GCD(i,n) = 1)$.</p>
<p><strong>Answer 1.33.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (filtered-accumulate combiner null-value term a next b filter)
</span></span><span class="line"><span class="cl">    (if (&gt; a b)
</span></span><span class="line"><span class="cl">        null-value
</span></span><span class="line"><span class="cl">        (if (filter a)
</span></span><span class="line"><span class="cl">            (combiner (term a) (filtered-accumulate combiner null-value (next a) next b filter))
</span></span><span class="line"><span class="cl">            (combiner null-value (filtered-accumulate combiner null-value (next a) next b filter))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.34.</strong>  Suppose we define the procedure</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f g)
</span></span><span class="line"><span class="cl">  (g 2))
</span></span></code></pre></div><p>Then we have</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(f square)
</span></span><span class="line"><span class="cl">4
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(f (lambda (z) (* z (+ z 1))))
</span></span><span class="line"><span class="cl">6
</span></span></code></pre></div><p>What happens if we (perversely) ask the interpreter to evaluate the combination <code>(f f)</code>? Explain.</p>
<p><strong>Answer 1.34.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (f f)
</span></span><span class="line"><span class="cl">=&gt; (f 2)
</span></span><span class="line"><span class="cl">=&gt; (2 2)
</span></span></code></pre></div><p>The third invocation will attempt to apply its argument, <code>2</code>, to <code>2</code>, resulting in error.</p>
<p><strong>Exercise 1.35.</strong>  Show that the golden ratio $\phi$ (section 1.2.2) is a fixed point of the transformation $x \mapsto 1 + 1/x$, and use this fact to compute $\phi$ by means of the <code>fixed-point</code> procedure.</p>
<p><strong>Answer 1.35.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0)
</span></span></code></pre></div><p><strong>Exercise 1.36.</strong>  Modify <code>fixed-point</code> so that it prints the sequence of approximations it generates, using the <code>newline</code> and <code>display</code> primitives shown in exercise 1.22. Then find a solution to $x^x = 1000$ by finding a fixed point of $x \mapsto \log(1000)/\log(x)$. (Use Scheme’s primitive <code>log</code> procedure, which computes natural logarithms.) Compare the number of steps this takes with and without average damping. (Note that you cannot start fixed-point with a guess of $1$, as this would cause division by $\log(1) = 0$.)</p>
<p><strong>Answer 1.36.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (display guess)
</span></span><span class="line"><span class="cl">        (newline)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(fixed-point (lambda(x) (/ (log 1000.0) (log x))) 2.0)
</span></span></code></pre></div><p><strong>Exercise 1.37.</strong></p>
<p>a. An infinite continued fraction is an expression of the form</p>
<p>$$
f=\frac{N_1}{D_1+\frac{N_2}{D_2+\frac{N_3}{D_3+…}}}
$$</p>
<p>As an example, one can show that the infinite continued fraction expansion with the $N_i$ and the $D_i$ all equal to $1$ produces $1/\phi$, where $\phi$ is the golden ratio (described in section 1.2.2). One way to approximate an infinite continued fraction is to truncate the expansion after a given number of terms. Such a truncation – a so-called <em>$k$-term finite continued fraction</em> – has the form</p>
<p>$$
\frac{N_1}{D_1+\frac{N_2}{…+\frac{N_k}{D_k}}}
$$</p>
<p>Suppose that <code>n</code> and <code>d</code> are procedures of one argument (the term index $i$) that return the $N_i$ and $D_i$ of the terms of the continued fraction. Define a procedure <code>cont-frac</code> such that evaluating <code>(cont-frac n d k)</code> computes the value of the $k$-term finite continued fraction. Check your procedure by approximating $1/\phi$ using</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(cont-frac (lambda (i) 1.0)
</span></span><span class="line"><span class="cl">           (lambda (i) 1.0)
</span></span><span class="line"><span class="cl">           k)
</span></span></code></pre></div><p>for successive values of <code>k</code>. How large must you make <code>k</code> in order to get an approximation that is accurate to $4$ decimal places?</p>
<p>b. If your <code>cont-frac</code> procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.</p>
<p><strong>Answer 1.37.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (+ (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (con-frac-iter n d k)
</span></span><span class="line"><span class="cl">    (define (frac-iter i result)
</span></span><span class="line"><span class="cl">        (if (= i 0)
</span></span><span class="line"><span class="cl">            result
</span></span><span class="line"><span class="cl">            (frac-iter (- i 1) (/ (n i) (+ (d i) result)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        (frac-iter (- k 1) (/ (n k) (d k)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(con-frac (lambda(i) 1.0) (lambda(i) 1.0) 10)
</span></span></code></pre></div><p><strong>Exercise 1.38.</strong>  In 1737, the Swiss mathematician Leonhard Euler published a memoir <em>De Fractionibus Continuis</em>, which included a continued fraction expansion for $e - 2$, where $e$ is the base of the natural logarithms. In this fraction, the $E_i$ are all $1$, and the $D_i$ are successively $1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, …$. Write a program that uses your <code>cont-frac</code> procedure from exercise 1.37 to approximate $e$, based on Euler’s expansion.</p>
<p><strong>Answer 1.38.</strong></p>
<p>$$
D_i=
\begin{cases}
2(i+1)/3,  &amp; \text{if } i\bmod 3 = 2;<br>
1, &amp; \text{if } i\bmod 3 \neq  2.
\end{cases}
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (+ (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (eular k)
</span></span><span class="line"><span class="cl">    (+ 2.0 (con-frac 
</span></span><span class="line"><span class="cl">        (lambda(i) 1)
</span></span><span class="line"><span class="cl">        (lambda(i)
</span></span><span class="line"><span class="cl">            (if (= (remainder i 3) 2)
</span></span><span class="line"><span class="cl">                (/ (+ i 1) 1.5)
</span></span><span class="line"><span class="cl">                1
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        k
</span></span><span class="line"><span class="cl">    ))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(eular 100)
</span></span></code></pre></div><p><strong>Exercise 1.39.</strong>  A continued fraction representation of the tangent function was published in 1770 by the German mathematician J.H. Lambert:</p>
<p>$$
\tan x  = \frac{x}{1-\frac{x^2}{3-\frac{x^2}{5-…}}}
$$</p>
<p>where $x$ is in radians. Define a procedure <code>(tan-cf x k)</code> that computes an approximation to the tangent function based on Lambert’s formula. <code>K</code> specifies the number of terms to compute, as in exercise 1.37.</p>
<p><strong>Answer 1.39.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (con-frac n d k)
</span></span><span class="line"><span class="cl">    (define (frac i)
</span></span><span class="line"><span class="cl">        (if (&lt; i k)
</span></span><span class="line"><span class="cl">            (/ (n i) (- (d i) (frac (+ i 1))))
</span></span><span class="line"><span class="cl">            (/ (n i) (d i))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (frac 1)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (tan-cf x k)
</span></span><span class="line"><span class="cl">    (con-frac 
</span></span><span class="line"><span class="cl">        (lambda (i) (
</span></span><span class="line"><span class="cl">            if (= i 1)
</span></span><span class="line"><span class="cl">                x
</span></span><span class="line"><span class="cl">                (* x x)
</span></span><span class="line"><span class="cl">        ))
</span></span><span class="line"><span class="cl">        (lambda (i) (
</span></span><span class="line"><span class="cl">            - (* 2 i) 1
</span></span><span class="line"><span class="cl">        ))
</span></span><span class="line"><span class="cl">        k
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.40.</strong>  Define a procedure <code>cubic</code> that can be used together with the <code>newtons-method</code> procedure in expressions of the form</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(newtons-method (cubic a b c) 1)
</span></span></code></pre></div><p>to approximate zeros of the cubic $x^3 + ax^2 + bx + c$.</p>
<p><strong>Answer 1.40.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cubic a b c)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (+
</span></span><span class="line"><span class="cl">            (cube x)
</span></span><span class="line"><span class="cl">            (* a (square x))
</span></span><span class="line"><span class="cl">            (* b x)
</span></span><span class="line"><span class="cl">            c
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cube x)
</span></span><span class="line"><span class="cl">    (* x x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.41.</strong>  Define a procedure <code>double</code> that takes a procedure of one argument as argument and returns a procedure that applies the original procedure twice. For example, if <code>inc</code> is a procedure that adds $1$ to its argument, then <code>(double inc)</code> should be a procedure that adds $2$. What value is returned by</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(((double (double double)) inc) 5)
</span></span></code></pre></div><p><strong>Answer 1.41.</strong></p>
<p>We guess the procedure <code>double</code> is:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double f)
</span></span><span class="line"><span class="cl">	(lambda (x) (f (f x)))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p>Then:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (((double (double double)) inc) 5) 
</span></span><span class="line"><span class="cl">=&gt; (((double (lambda (x) (double (double x)))) inc) 5) 
</span></span><span class="line"><span class="cl">=&gt; ((double (double (double (double inc)))) 5)
</span></span></code></pre></div><p>Since there are 4 <code>double</code> procedures, <code>call</code> procedure is invoked $2^4 = 16$ times. Thus, result is $5 + 16 = 21$</p>
<p><strong>Exercise 1.42.</strong>  Let $f$ and $g$ be two one-argument functions. The composition $f$ after $g$ is defined to be the function $x \mapsto  f(g(x))$. Define a procedure <code>compose</code> that implements composition. For example, if inc is a procedure that adds $1$ to its argument,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">((compose square inc) 6)
</span></span><span class="line"><span class="cl">49
</span></span></code></pre></div><p><strong>Answer 1.42.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.43.</strong>  If $f$ is a numerical function and $n$ is a positive integer, then we can form the $n$th repeated application of $f$, which is defined to be the function whose value at $x$ is $f(f(…(f(x))…))$. For example, if $f$ is the function $x \mapsto  x + 1$, then the $n$th repeated application of $f$ is the function $x \mapsto  x + n$. If $f$ is the operation of squaring a number, then the $n$th repeated application of $f$ is the function that raises its argument to the $2^n$th power. Write a procedure that takes as inputs a procedure that computes $f$ and a positive integer $n$ and returns the procedure that computes the $n$th repeated application of $f$. Your procedure should be able to be used as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">((repeated square 2) 5)
</span></span><span class="line"><span class="cl">625
</span></span></code></pre></div><p>Hint: You may find it convenient to use <code>compose</code> from exercise 1.42.</p>
<p><strong>Answer 1.43.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.44.</strong>  The idea of <em>smoothing</em> a function is an important concept in signal processing. If $f$ is a function and $dx$ is some small number, then the smoothed version of $f$ is the function whose value at a point $x$ is the average of $f(x - dx)$, $f(x)$, and $f(x + dx)$. Write a procedure smooth that takes as input a procedure that computes $f$ and returns a procedure that computes the smoothed $f$. It is sometimes valuable to repeatedly smooth a function (that is, smooth the smoothed function, and so on) to obtained the <em>$n$-fold smoothed function</em>. Show how to generate the $n$-fold smoothed function of any given function using $smooth$ and $repeated$ from exercise 1.43.</p>
<p><strong>Answer 1.44.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smooth f)
</span></span><span class="line"><span class="cl">    (lambda (x)
</span></span><span class="line"><span class="cl">        (/ (+
</span></span><span class="line"><span class="cl">                (f (- x dx))
</span></span><span class="line"><span class="cl">                (f x)
</span></span><span class="line"><span class="cl">                (f (+ x dx))
</span></span><span class="line"><span class="cl">           )
</span></span><span class="line"><span class="cl">           3 
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (n-fold-smooth f n)
</span></span><span class="line"><span class="cl">    ((repeated smooth n) f)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.45.</strong>  We saw in section 1.3.3 that attempting to compute square roots by naively finding a fixed point of $y \mapsto x/y$ does not converge, and that this can be fixed by average damping. The same method works for finding cube roots as fixed points of the average-damped $y \mapsto x/y^2$. Unfortunately, the process does not work for fourth roots – a single average damp is not enough to make a fixed-point search for $y \mapsto x/y^3$ converge. On the other hand, if we average damp twice (i.e., use the average damp of the average damp of $y \mapsto  x/y^3$) the fixed-point search does converge. Do some experiments to determine how many average damps are required to compute $n$th roots as a fixed-point search based upon repeated average damping of $y \mapsto x/y^{n-1}$. Use this to implement a simple procedure for computing nth roots using <code>fixed-point</code>, <code>average-damp</code>, and the <code>repeated</code> procedure of exercise 1.43. Assume that any arithmetic operations you need are available as primitives.</p>
<p><strong>Answer 1.45.</strong> Here reference <a href="http://www.billthelizard.com/2010/08/sicp-145-computing-nth-roots.html">SICP 1.45: Computing nth roots</a></p>
<p>To fix the problem, we need to increase the number of times invoking <code>average-damp</code>. And we find out the number of average damps, $a$, we can say:</p>
<p>$$
n_{\text{max}} = 2^{a+1} - 1 \
a =  \lfloor \log _2{n} \rfloor
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (nth-root x n)
</span></span><span class="line"><span class="cl">    (fixed-point
</span></span><span class="line"><span class="cl">        ((repeated average-damp (floor (/ (log x) (log 2))))
</span></span><span class="line"><span class="cl">            (lambda (y) (/ x (expt y (- n 1))))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        1.0
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (compose f g)
</span></span><span class="line"><span class="cl">    (lambda(x)
</span></span><span class="line"><span class="cl">        (f (g x))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (repeated f n)
</span></span><span class="line"><span class="cl">   (if (&lt; n 1)
</span></span><span class="line"><span class="cl">        (lambda(x) x)
</span></span><span class="line"><span class="cl">        (compose f (repeated f (- n 1)))
</span></span><span class="line"><span class="cl">   ) 
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define tolerance 0.00001)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fixed-point f first-guess)
</span></span><span class="line"><span class="cl">    (define (close-enough? v1 v2)
</span></span><span class="line"><span class="cl">        (&lt; (abs (- v1 v2)) tolerance)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (define (try guess)
</span></span><span class="line"><span class="cl">        (let ((next (f guess)))
</span></span><span class="line"><span class="cl">            (if (close-enough? guess next)
</span></span><span class="line"><span class="cl">                next
</span></span><span class="line"><span class="cl">                (try next)
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    (try first-guess)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (average-damp f)
</span></span><span class="line"><span class="cl">    (define (average x y)
</span></span><span class="line"><span class="cl">        (/ (+ x y) 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (lambda (x) (average x (f x)))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (expt b n)
</span></span><span class="line"><span class="cl">    (define (even? n) (= (remainder n 2) 0))
</span></span><span class="line"><span class="cl">    (define (square x) (* x x))
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= n 0) 1)
</span></span><span class="line"><span class="cl">        ((even? n) (square (expt b (/ n 2))))
</span></span><span class="line"><span class="cl">        (else (* b (expt b (- n 1))))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.46.</strong>  Several of the numerical methods described in this chapter are instances of an extremely general computational strategy known as <em>iterative improvement</em>. Iterative improvement says that, to compute something, we start with an initial guess for the answer, test if the guess is good enough, and otherwise improve the guess and continue the process using the improved guess as the new guess. Write a procedure <code>iterative-improve</code> that takes two procedures as arguments: a method for telling whether a guess is good enough and a method for improving a guess. <code>Iterative-improve</code> should return as its value a procedure that takes a guess as argument and keeps improving the guess until it is good enough. Rewrite the sqrt procedure of section 1.1.7 and the <code>fixed-point</code> procedure of section 1.3.3 in terms of <code>iterative-improve</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (close-enough? v1 v2) 
</span></span><span class="line"><span class="cl">   (define tolerance 1.e-6) 
</span></span><span class="line"><span class="cl">   (&lt; (/ (abs (- v1 v2)) v2)  tolerance)) 
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">(define (iterative-improve improve close-enough?) 
</span></span><span class="line"><span class="cl">   (lambda (x) 
</span></span><span class="line"><span class="cl">     (let ((xim (improve x))) 
</span></span><span class="line"><span class="cl">       (if (close-enough? x xim) 
</span></span><span class="line"><span class="cl">           xim 
</span></span><span class="line"><span class="cl">         ((iterative-improve improve close-enough?) xim)) 
</span></span><span class="line"><span class="cl">       ))) 
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl">(define (sqrt x) 
</span></span><span class="line"><span class="cl">   ((iterative-improve   
</span></span><span class="line"><span class="cl">     (lambda (y) 
</span></span><span class="line"><span class="cl">       (/ (+ (/ x y) y) 2)) 
</span></span><span class="line"><span class="cl">     close-enough?) 1.0))
</span></span></code></pre></div>]]></description></item><item><title>Building Abstractions with Procedures Section 2 - Part 2</title><link>https://blog.terryx.com/posts/sicp-1-2-2/</link><pubDate>Tue, 20 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/sicp-1-2-2/</guid><description><![CDATA[<h2 id="section-12-procedures-and-the-processes-they-generate">Section 1.2 Procedures and the Processes They Generate</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 1.20.</strong>  The process that a procedure generates is of course dependent on the rules used by the interpreter. As an example, consider the iterative <code>gcd</code> 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 <code>(gcd 206 40)</code> and indicate the <code>remainder</code> operations that are actually performed. How many <code>remainder</code> operations are actually performed in the normal-order evaluation of <code>(gcd 206 40)</code>? In the applicative-order evaluation?</p>
<p><strong>Answer 1.20.</strong></p>
<p><em>Normal-order evaluation</em>: fully expand and then reduce. 18 total <code>remainder</code>.</p>
<p><em>Applicative-order evaluation</em>: evaluate arguments and then apply operands. 4 total <code>remainder</code>.</p>
<p><strong>Exercise 1.21.</strong>  Use the smallest-divisor procedure to find the smallest divisor of each of the following numbers: $199$, $1999$, $19999$.</p>
<p><strong>Answer 1.21.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">    (find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">    (cond ((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">          ((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">          (else (find-divisor n (+ test-divisor 1)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">    (= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(smallest-divisor 199) =&gt; 199
</span></span><span class="line"><span class="cl">(smallest-divisor 1999) =&gt; 1999
</span></span><span class="line"><span class="cl">(smallest-divisor 19999) =&gt; 7
</span></span></code></pre></div><p><strong>Exercise 1.22.</strong>  Most Lisp implementations include a primitive called <code>runtime</code> that returns an integer that specifies the amount of time the system has been running (measured, for example, in microseconds). The following <code>timed-prime-test</code> procedure, when called with an integer $n$, prints $n$ and checks to see if $n$ is prime. If $n$ is prime, the procedure prints three asterisks followed by the amount of time used in performing the test.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (timed-prime-test n)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display n)
</span></span><span class="line"><span class="cl">  (start-prime-test n (runtime)))
</span></span><span class="line"><span class="cl">(define (start-prime-test n start-time)
</span></span><span class="line"><span class="cl">  (if (prime? n)
</span></span><span class="line"><span class="cl">      (report-prime (- (runtime) start-time))))
</span></span><span class="line"><span class="cl">(define (report-prime elapsed-time)
</span></span><span class="line"><span class="cl">  (display &#34; *** &#34;)
</span></span><span class="line"><span class="cl">  (display elapsed-time))
</span></span></code></pre></div><p>Using this procedure, write a procedure <code>search-for-primes</code> that checks the primality of consecutive odd integers in a specified range. Use your procedure to find the three smallest primes larger than $1000$; larger than $10,000$; larger than $100,000$; larger than $1,000,000$. Note the time needed to test each prime. Since the testing algorithm has order of growth of $\theta(\sqrt n)$, you should expect that testing for primes around $10,000$ should take about $\sqrt{10}$ times as long as testing for primes around $1000$. Do your timing data bear this out? How well do the data for $100,000$ and $1,000,000$ support the $\sqrt n$ prediction? Is your result compatible with the notion that programs on your machine run in time proportional to the number of steps required for the computation?</p>
<p><strong>Answer 1.22.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define runtime real-time-clock)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (timed-prime-test n)
</span></span><span class="line"><span class="cl">  (newline)
</span></span><span class="line"><span class="cl">  (display n)
</span></span><span class="line"><span class="cl">  (start-prime-test n (runtime)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (start-prime-test n start-time)
</span></span><span class="line"><span class="cl">  (if (prime? n)
</span></span><span class="line"><span class="cl">      (report-prime (- (runtime) start-time))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (report-prime elapsed-time)
</span></span><span class="line"><span class="cl">  (display &#34; *** &#34;)
</span></span><span class="line"><span class="cl">  (display elapsed-time))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">	(cond 
</span></span><span class="line"><span class="cl">		((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">		((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">		(else (find-divisor n (+ test-divisor 1)))
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">	(* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">	(= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">	(find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">	(= n (smallest-divisor n))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (search-for-primes start end)
</span></span><span class="line"><span class="cl">	(if (even? start)
</span></span><span class="line"><span class="cl">		(search-for-primes (+ start 1) end)
</span></span><span class="line"><span class="cl">		(cond 
</span></span><span class="line"><span class="cl">			((&lt; start end) (timed-prime-test start)
</span></span><span class="line"><span class="cl">			(search-for-primes (+ start 2) end))
</span></span><span class="line"><span class="cl">		)
</span></span><span class="line"><span class="cl">	)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(search-for-primes 1000000 1000100)
</span></span></code></pre></div><p><strong>Exercise 1.23.</strong>  The <code>smallest-divisor</code> procedure shown at the start of this section does lots of needless testing: After it checks to see if the number is divisible by $2$ there is no point in checking to see if it is divisible by any larger even numbers. This suggests that the values used <code>for test-divisor</code> should not be $2, 3, 4, 5, 6, …$, but rather $2, 3, 5, 7, 9, …$. To implement this change, define a procedure next that returns $3$ if its input is equal to $2$ and otherwise returns its input plus $2$. Modify the <code>smallest-divisor</code> procedure to use <code>(next test-divisor)</code> instead of <code>(+ test-divisor 1)</code>. With <code>timed-prime-test</code> incorporating this modified version of <code>smallest-divisor</code>, run the test for each of the $12$ primes found in exercise 1.22. Since this modification halves the number of test steps, you should expect it to run about twice as fast. Is this expectation confirmed? If not, what is the observed ratio of the speeds of the two algorithms, and how do you explain the fact that it is different from $2$?</p>
<p><strong>Answer 1.23.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (find-divisor n test-divisor)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((&gt; (square test-divisor) n) n)
</span></span><span class="line"><span class="cl">        ((divides? test-divisor n) test-divisor)
</span></span><span class="line"><span class="cl">        (else (find-divisor n (next test-divisor)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (next test-divisor)
</span></span><span class="line"><span class="cl">    (if (= test-divisor 2) (+ test-divisor 1)
</span></span><span class="line"><span class="cl">                           (+ test-divisor 2)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (divides? a b)
</span></span><span class="line"><span class="cl">    (= (remainder b a) 0)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (smallest-divisor n)
</span></span><span class="line"><span class="cl">    (find-divisor n 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (= (smallest-divisor n) n)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.24.</strong>  Modify the timed-prime-test procedure of exercise 1.22 to use <code>fast-prime?</code> (the Fermat method), and test each of the $12$ primes you found in that exercise. Since the Fermat test has  $\theta (\log n)$ growth, how would you expect the time to test primes near $1,000,000$ to compare with the time needed to test primes near 1000? Do your data bear this out? Can you explain any discrepancy you find?</p>
<p><strong>Answer 1.24.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp) (remainder (square (expmod base (/ exp 2) m)) m))
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fermat-test n)
</span></span><span class="line"><span class="cl">    (define (try-it a)
</span></span><span class="line"><span class="cl">        (= (expmod a n n) a)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (try-it (+ 1 (random (- n 1))))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-prime? n times)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= times 0) true)
</span></span><span class="line"><span class="cl">        ((fermat-test n) (fast-prime? n (- times 1)))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (fast-prime? n 100 )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.25.</strong>  Alyssa P. Hacker complains that we went to a lot of extra work in writing <code>expmod</code>. After all, she says, since we already know how to compute exponentials, we could have simply written</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">  (remainder (fast-expt base exp) m))
</span></span></code></pre></div><p>Is she correct? Would this procedure serve as well for our fast prime tester? Explain.</p>
<p><strong>Answer 1.25.</strong>  Scheme is able to handle arbitrary-precision arithmetic, but arithmetic with arbitrarily long numbers is computationally expensive. This means that we get the correct results, but it takes considerably longer.</p>
<p><strong>Exercise 1.26.</strong>  Louis Reasoner is having great difficulty doing exercise 1.24. His <code>fast-prime?</code> test seems to run more slowly than his <code>prime?</code> test. Louis calls his friend Eva Lu Ator over to help. When they examine Louis’s code, they find that he has rewritten the <code>expmod</code> procedure to use an explicit multiplication, rather than calling square:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">  (cond ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp)
</span></span><span class="line"><span class="cl">         (remainder (* (expmod base (/ exp 2) m)
</span></span><span class="line"><span class="cl">                       (expmod base (/ exp 2) m))
</span></span><span class="line"><span class="cl">                    m))
</span></span><span class="line"><span class="cl">        (else
</span></span><span class="line"><span class="cl">         (remainder (* base (expmod base (- exp 1) m))
</span></span><span class="line"><span class="cl">                    m))))
</span></span></code></pre></div><p>“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 $\theta (\log n)$ process into a $\theta (n)$ process.’’ Explain.</p>
<p><strong>Answer 1.26.</strong> Let $n$ is exponent which can generate a complete binary tree recursion. The depth of the tree is $\log n + 1$, the total number of nodes is $2^{\log n + 1} - 1$, is $2n -1 = \theta (n)$.</p>
<p><strong>Exercise 1.27.</strong>  Demonstrate that the Carmichael numbers listed in footnote 47 really do fool the Fermat test. That is, write a procedure that takes an integer $n$ and tests whether $a^n$ is congruent to $a$ modulo $n$ for every $a &lt; n$, and try your procedure on the given Carmichael numbers.</p>
<p><strong>Answer 1.27.</strong> Carmichael numbers fools Fermat test.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond 
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp) (remainder (square (expmod base (/ exp 2) m)) m))
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fermat-test n test-value)
</span></span><span class="line"><span class="cl">    (define (try-it a)
</span></span><span class="line"><span class="cl">        (= (expmod a n n) a)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (try-it test-value)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-prime? n times)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= times 0) true)
</span></span><span class="line"><span class="cl">        ((fermat-test n times) (fast-prime? n (- times 1)))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (fast-prime? n (- n 1))
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(prime? 561)
</span></span><span class="line"><span class="cl">(prime? 1105)
</span></span><span class="line"><span class="cl">(prime? 1729)
</span></span><span class="line"><span class="cl">(prime? 2465)
</span></span></code></pre></div><p><strong>Exercise 1.28.</strong>  One variant of the Fermat test that cannot be fooled is called the <em>Miller-Rabin test</em> (Miller 1976; Rabin 1980). This starts from an alternate form of Fermat’s Little Theorem, which states that if $n$ is a prime number and $a$ is any positive integer less than $n$, then $a$ raised to the $(n - 1)$st power is congruent to $1$ modulo $n$. To test the primality of a number $n$ by the Miller-Rabin test, we pick a random number $a&lt;n$ and raise $a$ to the $(n - 1)$st power modulo $n$ using the <code>expmod</code> procedure. However, whenever we perform the squaring step in <code>expmod</code>, we check to see if we have discovered a “nontrivial square root of $1$ modulo $n$,” that is, a number not equal to $1$ or $n - 1$ whose square is equal to $1$ modulo $n$. It is possible to prove that if such a nontrivial square root of $1$ exists, then $n$ is not prime. It is also possible to prove that if $n$ is an odd number that is not prime, then, for at least half the numbers $a&lt;n$, computing $a^{n-1}$ in this way will reveal a nontrivial square root of $1$ modulo $n$. (This is why the Miller-Rabin test cannot be fooled.) Modify the <code>expmod</code> procedure to signal if it discovers a nontrivial square root of $1$, and use this to implement the Miller-Rabin test with a procedure analogous to <code>fermat-test</code>. Check your procedure by testing various known primes and non-primes. Hint: One convenient way to make <code>expmod</code> signal is to have it return $0$.</p>
<p><strong>Answer 1.28.</strong> I got stuck in the exercise for hours. After reading other resources about Miller-Rabin test, I find out we don’t worry about the proof that “if such a nontrivial square root of $1$ exists, then $n$ is not prime”. Just know about the condition apply to the procedure.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (expmod base exp m)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= exp 0) 1)
</span></span><span class="line"><span class="cl">        ((even? exp)
</span></span><span class="line"><span class="cl">            (let ((x (expmod base (/ exp 2) m)))
</span></span><span class="line"><span class="cl">                (if (non-trivial-sqrt? x m) 0 (remainder (square x) m))
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">        (else (remainder (* base (expmod base (- exp 1) m)) m))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (non-trivial-sqrt? n m)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= n 1) false)
</span></span><span class="line"><span class="cl">        ((= n (- m 1)) false)
</span></span><span class="line"><span class="cl">        (else (= (remainder (square n) m) 1))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (miller-rabin-test a n)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= a 0) true)
</span></span><span class="line"><span class="cl">        ((= (expmod a (- n 1) n ) 1) (miller-rabin-test (- a 1) n))
</span></span><span class="line"><span class="cl">        (else false)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (prime? n)
</span></span><span class="line"><span class="cl">    (miller-rabin-test (- n 1) n)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(prime? 561)
</span></span><span class="line"><span class="cl">(prime? 1105)
</span></span><span class="line"><span class="cl">(prime? 1729)
</span></span><span class="line"><span class="cl">(prime? 2465)
</span></span></code></pre></div>]]></description></item><item><title>Building Abstractions with Procedures Section 2 - Part 1</title><link>https://blog.terryx.com/posts/scip-1-2/</link><pubDate>Fri, 16 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/scip-1-2/</guid><description><![CDATA[<h2 id="section-12-procedures-and-the-processes-they-generate">Section 1.2 Procedures and the Processes They Generate</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SCIP</a>.</p>
<p><strong>Exercise 1.9.</strong> Each of the following two procedures defines a method for adding two positive integers in terms of the procedures <code>inc</code>, which increments its argument by 1, and dec, which decrements its argument by 1.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (+ a b)
</span></span><span class="line"><span class="cl">  (if (= a 0)
</span></span><span class="line"><span class="cl">      b
</span></span><span class="line"><span class="cl">      (inc (+ (dec a) b))))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (+ a b)
</span></span><span class="line"><span class="cl">  (if (= a 0)
</span></span><span class="line"><span class="cl">      b
</span></span><span class="line"><span class="cl">      (+ (dec a) (inc b))))
</span></span></code></pre></div><p>Using the substitution model, illustrate the process generated by each procedure in evaluating <code>(+ 4 5)</code>. Are these processes iterative or recursive?</p>
<p><strong>Answer 1.9.</strong></p>
<p>For the first process, it is recursive:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (+ 4 5)
</span></span><span class="line"><span class="cl">=&gt; (+ 1 ( + 3 5))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 2 5)))
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 1 (+ 1 (5)))))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (+ 1 (6))))
</span></span><span class="line"><span class="cl">=&gt; (+ 1 (+ 1 (7)))
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; 9
</span></span></code></pre></div><p>For the second process, it is iterative:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (+ 4 5)
</span></span><span class="line"><span class="cl">=&gt; (+ 3 6)
</span></span><span class="line"><span class="cl">=&gt; (+ 2 7)
</span></span><span class="line"><span class="cl">=&gt; ...
</span></span><span class="line"><span class="cl">=&gt; (+ 0 8)
</span></span><span class="line"><span class="cl">=&gt; 8
</span></span></code></pre></div><p><strong>Exercise 1.10.</strong>  The following procedure computes a mathematical function called Ackermann’s function.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (A x y)
</span></span><span class="line"><span class="cl">  (cond ((= y 0) 0)
</span></span><span class="line"><span class="cl">        ((= x 0) (* 2 y))
</span></span><span class="line"><span class="cl">        ((= y 1) 2)
</span></span><span class="line"><span class="cl">        (else (A (- x 1)
</span></span><span class="line"><span class="cl">                 (A x (- y 1))))))
</span></span></code></pre></div><p>What are the values of the following expressions?</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(A 1 10)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(A 2 4)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(A 3 3)
</span></span></code></pre></div><p>Consider the following procedures, where A is the procedure defined above:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (f n) (A 0 n))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (g n) (A 1 n))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (h n) (A 2 n))
</span></span></code></pre></div><p>Give concise mathematical definitions for the functions computed by the procedures <em>f</em>, <em>g</em>, and <em>h</em> for positive integer values of <em>n</em>.</p>
<p><strong>Answer 1.10.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(A 1 10) = 2^10 = 1024
</span></span><span class="line"><span class="cl">(A 2 4) = 65536
</span></span><span class="line"><span class="cl">(A 3 3) = 65536
</span></span></code></pre></div><p>$$
A(0,n)=f(n)=2n
$$</p>
<p>$$
A(1,n)=g(n)=2^n
$$</p>
<p>$$
A(2,n)=h(n) = \overbrace{(2^{(2^{(2^{…})})})}^{n ~times}
$$</p>
<p><strong>Exercise 1.11.</strong>  A function <code>f</code> is defined by the rule that <code>f(n) = n if n&lt;3 and f(n) = f(n-1) + 2f(n-2) + 3f(n-3) if n&gt;3</code>. Write a procedure that computes <code>f</code> by means of a recursive process. Write a procedure that computes <code>f</code> by means of an iterative process.</p>
<p><strong>Answer 1.11.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (fun-recursive n)
</span></span><span class="line"><span class="cl">  (if (&lt; n 3)
</span></span><span class="line"><span class="cl">  n
</span></span><span class="line"><span class="cl">  (+ (fun-recursive (- n 1))
</span></span><span class="line"><span class="cl">     (* 2 (fun-recursive (- n 2)))
</span></span><span class="line"><span class="cl">     (* 3 (fun-recursive (- n 3)))
</span></span><span class="line"><span class="cl">     )) 
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fun-iter n a b cnt)
</span></span><span class="line"><span class="cl">     (if (= cnt 0)
</span></span><span class="line"><span class="cl">            n
</span></span><span class="line"><span class="cl">            (fun-iter (+ n (* 2 a) (* 3 b)) n a (- cnt 1))
</span></span><span class="line"><span class="cl">     )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fun-iterative n)
</span></span><span class="line"><span class="cl">    (fun-iter 2 1 0 (- n 2))
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.12.</strong> The following pattern of numbers is called Pascal’s triangle.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">				1
</span></span><span class="line"><span class="cl">			1		1
</span></span><span class="line"><span class="cl">		1		2		1
</span></span><span class="line"><span class="cl">	1		3		3		1
</span></span><span class="line"><span class="cl">1		4		6		4		1
</span></span><span class="line"><span class="cl">			   ...
</span></span></code></pre></div><p>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. Write a procedure that computes elements of Pascal’s triangle by means of a recursive process.</p>
<p><strong>Answer 1.12.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (pascal-triangle m n)
</span></span><span class="line"><span class="cl">    (if (or (= n 1) (= n m))
</span></span><span class="line"><span class="cl">        1
</span></span><span class="line"><span class="cl">        (+ (pascal-triangle (- m 1) (- n 1)) 
</span></span><span class="line"><span class="cl">           (pascal-triangle (- m 1) n))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.13.</strong>  Prove that Fib(n) is the closest integer to $\frac{\phi^{n}}{\sqrt{5}}$, where $\phi=\frac{1 + \sqrt{5}}{2}$.</p>
<p><strong>Answer 1.13.</strong></p>
<p><strong>Theorem 1</strong></p>
<p>$$
Fib(n)=\frac{\phi^n-\psi^n}{\sqrt{5}},\phi=\frac{1+\sqrt{5}}{2}, \psi=\frac{1-\sqrt{5}}{2}
$$</p>
<p><strong>Base Case</strong></p>
<p>$$
Fib(0)=0, Fib(1)=1
$$</p>
<p><strong>Induction Step</strong></p>
<p>\begin{align}
Fib(n-1)+Fib(n-2)&amp;=\frac{(\phi^{n-1}-\psi^{n-1})+(\phi^{n-2}-\psi^{n-2})}{\sqrt{5}}\
&amp;=\frac{(\phi^{n-1}+\phi^{n-2})-(\psi^{n-1}+\psi^{n-2})}{\sqrt{5}}\end{align}</p>
<p>Meanwhile,</p>
<p>\begin{align}
\phi+1=\frac{3+\sqrt{5}}{2}=\frac{6+2\sqrt{5}}{4}=(\frac{1+\sqrt{5}}{2})^2=\phi^2\
\psi+1=\frac{3-\sqrt{5}}{2}=\frac{6-2\sqrt{5}}{4}=(\frac{1-\sqrt{5}}{2})^2=\psi^2
\end{align}</p>
<p>Thus,</p>
<p>\begin{align}
Fib(n-1)+Fib(n-2)&amp;=\frac{\phi^{n-2}(\phi+1)-\psi^{n-2}(\psi+1)}{\sqrt{5}}\
&amp;=\frac{\phi^n-\psi^n}{\sqrt{5}}=Fib(n)
\end{align}</p>
<p><strong>Theorem 2</strong></p>
<p>\begin{align}
\frac{\psi^n}{\sqrt{5}} &lt; \frac{1}{2}
\end{align}</p>
<p><strong>Proof</strong></p>
<p>\begin{align}
\frac{\psi^0}{\sqrt{5}}&amp;\sim0.4472, \frac{\psi^1}{\sqrt{5}}\sim0.2764,…\
\frac{\psi^n}{\sqrt{5}}&amp;&lt;\frac{1}{2}
\end{align}</p>
<p>Therefore,</p>
<p>\begin{align}
Fib(n) &amp;= \frac{\phi^n-\psi^n}{\sqrt{5}} = \left[\frac{\phi^n-\psi^n}{\sqrt{5}}\right]\
&amp;=\left[\frac{\phi^n}{\sqrt{5}}\right]
\end{align}</p>
<p>Q.E.D.</p>
<p><strong>Exercise 1.14.</strong>  Draw the tree illustrating the process generated by the <code>count-change</code> procedure of section 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?</p>
<p><strong>Answer 1.14.</strong></p>
<p><img src="/images/20161217/tree-figure.png" alt=""  loading="lazy">
</p>
<p>Let the number of kinds of coins: $k$;
Amount of money: $n$;
Denominations: $d_1, d_2, …, d_k$.</p>
<p><strong>Orders of growth of the space</strong></p>
<p>The space required is proportional to the maximum depth of the tree.
Clearly, this means the maximum height is going to be linear in the amount $n$, or $\theta(n)$.</p>
<p><strong>Number of steps</strong></p>
<p><em>Basic case</em></p>
<p><img src="/images/20161217/tree-a.png" alt=""  loading="lazy">
</p>
<p>Let see the recursive tree of <code>(cc n 1)</code>, which number of steps is defined as $T(n,1)$. Clearly, we can calculate that $T(n,1)=2n+1=\theta(n)$.</p>
<p><em>Induction step</em></p>
<p><img src="/images/20161217/tree-b.png" alt=""  loading="lazy">
</p>
<p>Next, we look at the recursive tree of <code>(cc n k)</code>. We have:</p>
<p>$$
T(n,k)=\lfloor \frac{n}{d_k} \rfloor (T(n,k-1)+1)+2
$$</p>
<p>We can expand it further:</p>
<p>\begin{align}
T(n,k)&amp;=\lfloor \frac{n}{d_k} \rfloor (T(n,k-1)+1)+2 \
&amp;=\lfloor \frac{n}{d_k} \rfloor ((\lfloor \frac{n}{d_k} \rfloor T(n,k-2)+1)+2+1)+2 \
&amp;= \lfloor \frac{n}{d_k} \rfloor (… (\lfloor \frac{n}{d_k} \rfloor T(n,1)+1)+2 … +1)+2 \
&amp;= \theta(n^k)
\end{align}</p>
<p>Thus, we have $T(n,5) = \theta(n^5)$.</p>
<p><strong>Exercise 1.15.</strong> The sine of an angle (specified in radians) can be computed by making use of the approximation $sin x \approx x$ if $x$ is sufficiently small, and the trigonometric identity</p>
<p>$$
\sin x = 3 \sin \frac{x}{3} - 4 \sin^3 \frac{x}{3}
$$</p>
<p>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:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cube x) (* x x x))
</span></span><span class="line"><span class="cl">(define (p x) (- (* 3 x) (* 4 (cube x))))
</span></span><span class="line"><span class="cl">(define (sine angle)
</span></span><span class="line"><span class="cl">   (if (not (&gt; (abs angle) 0.1))
</span></span><span class="line"><span class="cl">       angle
</span></span><span class="line"><span class="cl">       (p (sine (/ angle 3.0)))))
</span></span></code></pre></div><p>a.  How many times is the procedure <code>p</code> applied when (sine 12.15) is evaluated?</p>
<p>b.  What is the order of growth in space and number of steps (as a function of $a$) used by the process generated by the sine procedure when <code>(sine a)</code> is evaluated?</p>
<p><strong>Answer 1.15.</strong></p>
<p>a. $\lceil \log_3 \frac{12.15}{0.1} \rceil = 5$.</p>
<p>b. The order of growth in space and number of steps are $\theta(\log n)$.</p>
<p><strong>Exercise 1.16.</strong>  Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps, as does <code>fast-expt</code>. (Hint: Using the observation that $(b^{n/2})^2 = (b^2)^{n/2}$, keep, along with the exponent $n$ and the base $b$, an additional state variable $a$, and define the state transformation in such a way that the product $ab^n$ is unchanged from state to state. At the beginning of the process $a$ is taken to be $1$, and the answer is given by the value of $a$ 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.)</p>
<p><strong>Answer 1.16.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">    (* x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (expt-iter b n a)
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= n 0) a)
</span></span><span class="line"><span class="cl">        ((even? n) (expt-iter (square b) (/ n 2) a))
</span></span><span class="line"><span class="cl">        (else (expt-iter b (- n 1) (* a b)))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-expt a n)
</span></span><span class="line"><span class="cl">    (expt-iter a n 1)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.17.</strong>  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 <code>expt</code> procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (* a b)
</span></span><span class="line"><span class="cl">  (if (= b 0)
</span></span><span class="line"><span class="cl">      0
</span></span><span class="line"><span class="cl">      (+ a (* a (- b 1)))))
</span></span></code></pre></div><p>This algorithm takes a number of steps that is linear in <code>b</code>. Now suppose we include, together with addition, operations <code>double</code>, which doubles an integer, and <code>halve</code>, which divides an (even) integer by $2$. Using these, design a multiplication procedure analogous to <code>fast-expt</code> that uses a logarithmic number of steps.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double x)
</span></span><span class="line"><span class="cl">    (+ x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (halve x)
</span></span><span class="line"><span class="cl">    (/ x 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (mult-iter a b )
</span></span><span class="line"><span class="cl">    (cond
</span></span><span class="line"><span class="cl">        ((= b 0) 0)
</span></span><span class="line"><span class="cl">        ((even? b) (mult-iter (double a) (halve b)))
</span></span><span class="line"><span class="cl">        (else (+ a (mult-iter a (- b 1) )))
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-mult a b)
</span></span><span class="line"><span class="cl">    (mult-iter a b)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.18.</strong>  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.</p>
<p><strong>Answer 1.18.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (double x)
</span></span><span class="line"><span class="cl">    (+ x x)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (halve x)
</span></span><span class="line"><span class="cl">    (/ x 2)
</span></span><span class="line"><span class="cl">)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (fast-mult a b)
</span></span><span class="line"><span class="cl">    (define (mult-iter a b acc)
</span></span><span class="line"><span class="cl">        (cond
</span></span><span class="line"><span class="cl">            ((= b 0) acc)
</span></span><span class="line"><span class="cl">            ((even? b) (mult-iter (double a) (halve b) acc))
</span></span><span class="line"><span class="cl">            (else (mult-iter a (- b 1) (+ acc a)))
</span></span><span class="line"><span class="cl">        )
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">    (mult-iter a b 0)
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.19.</strong> 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 <code>fib-iter</code> process of section 1.2.2: $a \rightarrow  a + b$ and $b \rightarrow a$. 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 $T^n$, the $n$th 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 $T_{pq}$, where $T_{pq}$ transforms the pair $(a,b)$ according to $a \leftarrow  bq + aq + ap$ and $b \leftarrow  bp + aq$. Show that if we apply such a transformation $T_{pq}$ twice, the effect is the same as using a single transformation $T_{p’q’}$ of the same form, and compute $p’$ and $q’$ in terms of $p$ and $q$. This gives us an explicit way to square these transformations, and thus we can compute $T^n$ using successive squaring, as in the <code>fast-expt</code> procedure. Put this all together to complete the following procedure, which runs in a logarithmic number of steps:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (fib n)
</span></span><span class="line"><span class="cl">  (fib-iter 1 0 0 1 n))
</span></span><span class="line"><span class="cl">(define (fib-iter a b p q count)
</span></span><span class="line"><span class="cl">  (cond ((= count 0) b)
</span></span><span class="line"><span class="cl">        ((even? count)
</span></span><span class="line"><span class="cl">         (fib-iter a
</span></span><span class="line"><span class="cl">                   b
</span></span><span class="line"><span class="cl">                   &lt;??&gt;      ; compute p&#39;
</span></span><span class="line"><span class="cl">                   &lt;??&gt;      ; compute q&#39;
</span></span><span class="line"><span class="cl">                   (/ count 2)))
</span></span><span class="line"><span class="cl">        (else (fib-iter (+ (* b q) (* a q) (* a p))
</span></span><span class="line"><span class="cl">                        (+ (* b p) (* a q))
</span></span><span class="line"><span class="cl">                        p
</span></span><span class="line"><span class="cl">                        q
</span></span><span class="line"><span class="cl">                        (- count 1)))))
</span></span></code></pre></div><p><strong>Answer 1.19.</strong></p>
<p>Define $a’$ and $b’$ by the definition of the transformation $T_{pq}$:</p>
<p>\begin{align}
a’ &amp;= qb + qa + pa = (p + q)a + qb \
b’ &amp;= qa + pb
\end{align}</p>
<p>Then, let $a’’$ and $b’’$ be the results of the transformation to $a’$ and $b’$ by applying the transformation once:</p>
<p>\begin{align}
a’’ &amp;= (p + q)a’ + qb’ = (p^2 + 2pq + 2q^2)a + (2pq + q^2)b \
b’’ &amp;= qa’ + pb’ = (2pq + q^2)a + (p^2 + q^2)b
\end{align}</p>
<p>Thus, we get the transformation to $p$ and $q$:</p>
<p>\begin{align}
p’ &amp;= p^2 + q^2 \
q’ &amp;= 2pq + q^2
\end{align}</p>
]]></description></item><item><title>Building Abstractions with Procedures Section 1</title><link>https://blog.terryx.com/posts/scip-1-1/</link><pubDate>Mon, 12 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.terryx.com/posts/scip-1-1/</guid><description><![CDATA[<h2 id="section-11-the-elements-of-programing">Section 1.1 The Elements of Programing</h2>
<p>Exercises in this section of <a href="https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs">SICP</a>.</p>
<p><strong>Exercise 1.1.</strong> Below is a sequence of expressions. What is the result printed by the interpreter in response to each expression? Assume that the sequence is to be evaluated in the order in which it is presented.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">10
</span></span><span class="line"><span class="cl">(+ 5 3 4)
</span></span><span class="line"><span class="cl">(- 9 1)
</span></span><span class="line"><span class="cl">(/ 6 2)
</span></span><span class="line"><span class="cl">(+ (* 2 4) (- 4 6))
</span></span><span class="line"><span class="cl">(define a 3)
</span></span><span class="line"><span class="cl">(define b (+ a 1))
</span></span><span class="line"><span class="cl">(+ a b (* a b))
</span></span><span class="line"><span class="cl">(= a b)
</span></span><span class="line"><span class="cl">(if (and (&gt; b a) (&lt; b (* a b)))
</span></span><span class="line"><span class="cl">    b
</span></span><span class="line"><span class="cl">    a)
</span></span><span class="line"><span class="cl">(cond ((= a 4) 6)
</span></span><span class="line"><span class="cl">      ((= b 4) (+ 6 7 a))
</span></span><span class="line"><span class="cl">      (else 25))
</span></span><span class="line"><span class="cl">(+ 2 (if (&gt; b a) b a))
</span></span><span class="line"><span class="cl">(* (cond ((&gt; a b) a)
</span></span><span class="line"><span class="cl">         ((&lt; a b) b)
</span></span><span class="line"><span class="cl">         (else -1))
</span></span><span class="line"><span class="cl">   (+ a 1))
</span></span></code></pre></div><p><strong>Answer 1.1.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">10
</span></span><span class="line"><span class="cl">12
</span></span><span class="line"><span class="cl">8
</span></span><span class="line"><span class="cl">3
</span></span><span class="line"><span class="cl">6
</span></span><span class="line"><span class="cl">a
</span></span><span class="line"><span class="cl">b
</span></span><span class="line"><span class="cl">19
</span></span><span class="line"><span class="cl">#f
</span></span><span class="line"><span class="cl">4
</span></span><span class="line"><span class="cl">16
</span></span><span class="line"><span class="cl">6
</span></span><span class="line"><span class="cl">16
</span></span></code></pre></div><p><strong>Exercise 1.2.</strong> Translate the following expression into prefix form</p>
<p>$$
\frac{5+4+(2-(3-6 + \frac{4}{5}))}{3(6-2)(2-7)}
$$</p>
<p><strong>Answer 1.2.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 3))))) (* 3 (- 6 2) (- 2 7)))
</span></span></code></pre></div><p><strong>Exercise 1.3.</strong> Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.</p>
<p><strong>Answer 1.3.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(DEFINE (SOS x y) (+ (* x x) (* y y)))
</span></span><span class="line"><span class="cl">(DEFINE (F x y z)
</span></span><span class="line"><span class="cl">	(COND ((AND (&lt;= x y) (&lt;= x z)) (SOS y z))
</span></span><span class="line"><span class="cl">	      ((AND (&lt;= y x) (&lt;= y z)) (SOS x z))
</span></span><span class="line"><span class="cl">	      ((AND (&lt;= z x) (&lt;= z y)) (SOS x y))
</span></span><span class="line"><span class="cl">	)	
</span></span><span class="line"><span class="cl">)
</span></span></code></pre></div><p><strong>Exercise 1.4.</strong> Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (a-plus-abs-b a b)
</span></span><span class="line"><span class="cl">  ((if (&gt; b 0) + -) a b))
</span></span></code></pre></div><p><strong>Answer 1.4.</strong></p>
<p>$$
a+|b|
$$</p>
<p><em>a</em> plus the absolute value of <em>b</em>.</p>
<p><strong>Exercise 1.5.</strong> Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (p) (p))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (test x y)
</span></span><span class="line"><span class="cl">  (if (= x 0)
</span></span><span class="line"><span class="cl">      0
</span></span><span class="line"><span class="cl">      y))
</span></span></code></pre></div><p>Then he evaluates the expression:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(test 0 (p))
</span></span></code></pre></div><p>What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form <code>if</code> is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)</p>
<p><strong>Answer 1.5.</strong></p>
<p>The applicative-order evaluation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (test 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (test 0 ((p)))
</span></span><span class="line"><span class="cl">=&gt; (test 0 (((p))))
</span></span></code></pre></div><p>As we see, the evaluation of <code>(test 0 (p))</code> is infinitive.</p>
<p>The normal-order evaluation:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">=&gt; (test 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (if (= 0 0) 0 (p))
</span></span><span class="line"><span class="cl">=&gt; (if #t 0 (p))
</span></span><span class="line"><span class="cl">=&gt; 0
</span></span></code></pre></div><p>The expression evaluates to <code>0</code>.</p>
<p><strong>Exercise 1.6.</strong>  Alyssa P. Hacker doesn’t see why if needs to be provided as a special form. “Why can’t I just define it as an ordinary procedure in terms of <code>cond</code>?” she asks. Alyssa’s friend Eva Lu Ator claims this can indeed be done, and she defines a new version of <code>if</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (new-if predicate then-clause else-clause)
</span></span><span class="line"><span class="cl">  (cond (predicate then-clause)
</span></span><span class="line"><span class="cl">        (else else-clause)))
</span></span></code></pre></div><p>Eva demonstrates the program for Alyssa:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(new-if (= 2 3) 0 5)
</span></span><span class="line"><span class="cl">5
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(new-if (= 1 1) 0 5)
</span></span><span class="line"><span class="cl">0
</span></span></code></pre></div><p>Delighted, Alyssa uses new-if to rewrite the square-root program:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (sqrt-iter guess x)
</span></span><span class="line"><span class="cl">  (new-if (good-enough? guess x)
</span></span><span class="line"><span class="cl">          guess
</span></span><span class="line"><span class="cl">          (sqrt-iter (improve guess x)
</span></span><span class="line"><span class="cl">                     x)))
</span></span></code></pre></div><p>What happens when Alyssa attempts to use this to compute square roots? Explain.</p>
<p><strong>Answer 1.6.</strong> I believe this program is incorrect, because <code>new-if</code> uses applicative-order evaluation. Thus, it always expands the <code>else-clause</code> and causes an infinite recursion. In contrast, <code>if</code> uses normal-order evaluation.</p>
<p><strong>Exercise 1.7.</strong>  The <code>good-enough</code>? test used in computing square roots will not be very effective for finding the square roots of very small numbers. Also, in real computers, arithmetic operations are almost always performed with limited precision. This makes our test inadequate for very large numbers. Explain these statements, with examples showing how the test fails for small and large numbers. An alternative strategy for implementing <code>good-enough</code>? is to watch how guess changes from one iteration to the next and to stop when the change is a very small fraction of the guess. Design a square-root procedure that uses this kind of end test. Does this work better for small and large numbers?</p>
<p><strong>Answer 1.7.</strong> The results are very inaccurate when calculating <code>sqrt(0.0001)</code> and <code>sqrt(100000000)</code>. We can modify <code>good-enough</code> using current guess and previous guess below:</p>
<p>$$
\frac{|G-G_{pre}|}{G}&lt;0.001
$$</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">  (&lt; (/ (abs (- guess prev-guess))
</span></span><span class="line"><span class="cl">        guess)
</span></span><span class="line"><span class="cl">     0.001))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sqrt-iter guess prev-guess x)
</span></span><span class="line"><span class="cl">  (if (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">    guess
</span></span><span class="line"><span class="cl">    (sqrt-iter (improve guess x)
</span></span><span class="line"><span class="cl">               guess
</span></span><span class="line"><span class="cl">               x)))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (sqrt x) 
</span></span><span class="line"><span class="cl">   (sqrt-iter 1.0 0 x))
</span></span></code></pre></div><p><strong>Exercise 1.8.</strong> Newton’s method for cube roots is based on the fact that if y is an approximation to the cube root of x, then a better approximation is given by the value</p>
<p>$$
\frac{x/y^2+2y}{3}
$$</p>
<p>Use this formula to implement a cube-root procedure analogous to the square-root procedure.</p>
<p><strong>Answer 1.8.</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plain" data-lang="plain"><span class="line"><span class="cl">(define (cub-iter guess prev-guess x)
</span></span><span class="line"><span class="cl">  (if (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">    guess
</span></span><span class="line"><span class="cl">    (cub-iter (improve guess x) guess x)
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (good-enough? guess prev-guess)
</span></span><span class="line"><span class="cl">  (&lt; (/ (abs (- guess prev-guess)) guess) 0.001)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (improve guess x)
</span></span><span class="line"><span class="cl">  (/ (+ (/ x (square guess)) (* 2 guess)) 3)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (square x)
</span></span><span class="line"><span class="cl">  (* x x)
</span></span><span class="line"><span class="cl">  )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(define (cubroot x) 
</span></span><span class="line"><span class="cl">  ((if (&lt; x 0) - +) (cub-iter (improve 1.0 (abs x)) 1 (abs x)))
</span></span><span class="line"><span class="cl">  )
</span></span></code></pre></div>]]></description></item></channel></rss>