<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;CkADR3w_cCp7ImA9WxBUGUo.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496</id><updated>2010-03-07T09:06:16.248-05:00</updated><title>Bill the Lizard</title><subtitle type="html">"The time has come," the Walrus said,
"To talk of many things..."</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.billthelizard.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>101</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/BillTheLizard" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="billthelizard" /><entry gd:etag="W/&quot;DE4BQXYyeip7ImA9WxBUF0g.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8215701883275556458</id><published>2010-03-04T21:18:00.003-05:00</published><updated>2010-03-04T21:42:30.892-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-04T21:42:30.892-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="miller-rabin" /><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.28: The Miller-Rabin test</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(&lt;span style="font-style: italic;"&gt;Note: The explanation of the Miller-Rabin test given in SICP is slightly different from every other source I've read.  I don't know if this was done purposefully by the authors for the sake of simplicity, or if the algorithm has simply evolved since SICP's publication. For the sake of consistency, I'm solving the exercise using the explanation given in the text.  If anyone is interested, Programming Praxis has &lt;a href="http://programmingpraxis.com/2009/05/01/primality-checking/"&gt;a short explanation of the algorithm&lt;/a&gt; and &lt;a href="http://programmingpraxis.com/2009/05/01/primality-checking/2/"&gt;an implementation in Scheme&lt;/a&gt;.  Naturally, you can also &lt;a href="http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test"&gt;read about it on Wikipedia&lt;/a&gt;.&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.28&lt;/span&gt; introduces a variation on the Fermat test that isn't fooled by &lt;a href="http://mathworld.wolfram.com/CarmichaelNumber.html"&gt;Carmichael numbers&lt;/a&gt; called the Miller-Rabin test.  We start with an alternate form of &lt;a href="http://mathworld.wolfram.com/FermatsLittleTheorem.html"&gt;Fermat's Little Theorem&lt;/a&gt;.  In exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-124-fermat-test.html"&gt;1.24&lt;/a&gt; we saw that if &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; is prime and &lt;span style="font-style: italic;"&gt;a&lt;/span&gt; is any positve integer &amp;lt; &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;,&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sup&gt;n&lt;/sup&gt; ≡ a (mod n)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;If we divide both sides of the congruency by &lt;span style="font-style: italic;"&gt;a&lt;/span&gt;, we get&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sup&gt;n-1&lt;/sup&gt; ≡ 1 (mod n)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;When we check this congruency using the &lt;code&gt;expmod&lt;/code&gt; procedure, at the squaring step we need to also check to see if we've discovered a "non-trivial square root of 1 modulo n," i.e., a number not equal to 1 or (n - 1) whose square is equal to 1 modulo n.  It's possible to prove that if a non-trivial square root of 1 exists, then n is not prime.  It's also possible to prove that if n is composite, then "for at least half the numbers a &amp;lt; n, computing a&lt;sup&gt;n-1&lt;/sup&gt; in this way will reveal a nontrivial square root of 1 modulo n." (I'm not sure if this is just a very conservative estimate or if it was the best information available at the time that SICP was written.  Every other source I've read claims that at least 3/4 of the bases you choose will reveal a nontrivial square root of 1 modulo n.)&lt;br /&gt;&lt;br /&gt;We're asked to modify the &lt;code&gt;expmod&lt;/code&gt; procedure to check for non-trivial square roots of 1 modulo n, and to use it to implement the Miller-Rabin test with a procedure analogous to the &lt;code&gt;fermat-test&lt;/code&gt; that we wrote before. We can check the new procedure by testing various known primes and non-primes.&lt;br /&gt;&lt;br /&gt;The first thing we need to do is modify the &lt;code&gt;square&lt;/code&gt; procedure so that it checks for a non-trivial square root of 1 modulo n.  We'll write a new procedure called &lt;code&gt;square-check&lt;/code&gt; that checks for two conditions:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;a number not equal to 1 or (n - 1)&lt;/li&gt;&lt;li&gt;whose square is equal to 1 modulo n&lt;/li&gt;&lt;/ol&gt;If both of these conditions are met, we'll signal that we've found a non-trivial square root by returning 0.  If these conditions are not met, we'll perform the remainder and squaring steps that &lt;code&gt;expmod&lt;/code&gt; did before.  Here's the complete code listing:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(require (lib "27.ss" "srfi"))&lt;br /&gt;&lt;br /&gt;(define (square-check x m)&lt;br /&gt;   (if (and (not (or (= x 1) (= x (- m 1))))&lt;br /&gt;            (= (remainder (* x x) m) 1))&lt;br /&gt;       0&lt;br /&gt;       (remainder (* x x) m)))&lt;br /&gt;&lt;br /&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;br /&gt;(define (expmod base exp m)&lt;br /&gt;   (cond ((= exp 0) 1)&lt;br /&gt;         ((even? exp)&lt;br /&gt;          (square-check (expmod base (/ exp 2) m) m))&lt;br /&gt;         (else&lt;br /&gt;          (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;                     m))))&lt;br /&gt;&lt;br /&gt;(define (miller-rabin-test n)&lt;br /&gt;   (define (try-it a)&lt;br /&gt;     (= (expmod a (- n 1) n) 1))&lt;br /&gt;   (try-it (+ 1 (random-integer (- n 1)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As with the &lt;code&gt;fermat-test&lt;/code&gt; procedure from exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-127-carmichael-numbers.html"&gt;1.27&lt;/a&gt;, prime numbers should always pass.  Composite numbers should have a high likelihood of failing, even the Carmichael numbers (so if you repeatedly test these values enough times, eventually you will see some false positives).  You can test several primes and composites in a Scheme interpreter.  Here's the output I got when I tested the first six Carmichael numbers.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (miller-rabin-test 561)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (miller-rabin-test 1105)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (miller-rabin-test 1729)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (miller-rabin-test 2465)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (miller-rabin-test 2821)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (miller-rabin-test 6601)&lt;br /&gt;#f&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8215701883275556458?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8215701883275556458/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8215701883275556458" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8215701883275556458?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8215701883275556458?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/03/sicp-exercise-128-miller-rabin-test.html" title="SICP Exercise 1.28: The Miller-Rabin test" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;A08EQ3g7cCp7ImA9WxBUE00.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-4142418909189290529</id><published>2010-02-27T17:08:00.012-05:00</published><updated>2010-02-27T17:30:02.608-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-27T17:30:02.608-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><title>"Goes to" Considered Harmful</title><content type="html">A few months ago the following question was asked (half jokingly) on Stack Overflow,&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator"&gt;What is the name of this operator: “--&gt;”?&lt;/a&gt;&lt;/blockquote&gt;The question includes the following C++ code:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;#include &amp;lt;stdio.h&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;    int x = 10;&lt;br /&gt;    while( x --&gt; 0 ) // x goes to 0&lt;br /&gt;    {&lt;br /&gt;        printf("%d ", x);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The output of this program is to simply count down from 9 to 0, printing each value.  As many others pointed out, "--&gt;" isn't a single operator at all, but two operators smashed together.  The condition of the &lt;code&gt;while&lt;/code&gt; loop above can be rewritten with proper spacing as:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;while( x-- &gt; 0 ) // x-- is greater than  0&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;a href="http://twitter.com/joshbloch"&gt;Joshua Bloch&lt;/a&gt; commented on the goes-to operator on Twitter yesterday.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/joshbloch/status/9690506542"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 161px;" src="http://1.bp.blogspot.com/_PnLYRqe0k9g/S4mZNwUO3aI/AAAAAAAAARs/ixK9vpSP0A8/s320/Josh-Bloch-Goes-To-Quote.png" alt="" id="BLOGGER_PHOTO_ID_5443050086241066402" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;He links to the results of a Google Code search for &lt;a href="http://www.google.com/codesearch?q=%22--%3E%22+lang:c&amp;amp;hl=en&amp;amp;btnG=Search+Code"&gt;instances of "--&gt;" in the wild&lt;/a&gt;.  The results are specific to the C programming language, but "--&gt;" turns up in similar searches for &lt;a href="http://www.google.com/codesearch?hl=en&amp;amp;lr=&amp;amp;q=%22--%3E%22+lang%3Ac%2B%2B&amp;amp;sbtn=Search"&gt;C++&lt;/a&gt; and &lt;a href="http://www.google.com/codesearch?hl=en&amp;amp;lr=&amp;amp;q=%22--%3E%22+lang%3Ajava&amp;amp;sbtn=Search"&gt;Java&lt;/a&gt; as well (and probably any other language that allows it).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What's the harm?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So what's so harmful about this bit of cleverness?  The main problem is that it's &lt;span style="font-style: italic;"&gt;too &lt;/span&gt;clever.  Any time you use standard operators in a non-standard way (even if the language specification doesn't strictly forbid it) you're negatively impacting the readability of your code.  In this specific case, the "--&gt;" operator isn't documented anywhere.  It's just not reasonable to expect other programmers to know what it means.&lt;br /&gt;&lt;br /&gt;On top of that, this situation isn't best handled by a &lt;code&gt;while&lt;/code&gt; loop to begin with.  If you know ahead of time how many iterations your loop needs to make, use a &lt;code&gt;for&lt;/code&gt; loop.  Kernighan and Richie covered this a very long time ago in &lt;a href="http://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628"&gt;The C Programming Language&lt;/a&gt;.  It's still true today.&lt;br /&gt;&lt;blockquote&gt;The &lt;code&gt;for&lt;/code&gt; is preferable when there is a simple initialization and increment, since it keeps the loop control statements close together and visible at the top of the loop.&lt;/blockquote&gt;This, of course, is also true for a simple decrementing loop.  The meaning of the following code should be obvious to any junior programmer.&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;int i;&lt;br /&gt;for( i = 9; i &gt;= 0; i-- )&lt;br /&gt;{&lt;br /&gt;    printf("%d ", i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Writing code that's "too clever" for other programmers to understand immediately just obfuscates your code needlessly.  You'll seem much cleverer to your colleagues if you write your code in a clear and readable style to begin with.  Besides that, using the common idioms of your language is probably the quickest way to reduce your &lt;a href="http://www.osnews.com/story/19266/WTFs_m"&gt;WTFs/minute score&lt;/a&gt; at your next code review.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-4142418909189290529?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/4142418909189290529/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=4142418909189290529" title="24 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4142418909189290529?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4142418909189290529?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/goes-to-considered-harmful.html" title="&quot;Goes to&quot; Considered Harmful" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_PnLYRqe0k9g/S4mZNwUO3aI/AAAAAAAAARs/ixK9vpSP0A8/s72-c/Josh-Bloch-Goes-To-Quote.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">24</thr:total></entry><entry gd:etag="W/&quot;C0AFRnY_eyp7ImA9WxBVGUo.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-6837804937445619064</id><published>2010-02-23T19:23:00.005-05:00</published><updated>2010-02-23T19:35:17.843-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-23T19:35:17.843-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="fermat" /><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.27: Carmichael numbers</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.27&lt;/span&gt; asks us to demonstrate that the first six &lt;a href="http://mathworld.wolfram.com/CarmichaelNumber.html"&gt;Carmicheal numbers&lt;/a&gt; (561, 1105, 1729, 2465, 2821, and 6601) really do fool the &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-124-fermat-test.html"&gt;Fermat test&lt;/a&gt;.  We're to write a procedure that takes an integer n and tests whether a&lt;sup&gt;n&lt;/sup&gt; is congruent to a modulo n for every value less than n, then test the procedure on each of the Carmichael numbers listed.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;fermat-test&lt;/code&gt; procedure that we first saw in exercise 1.24 is a good starting point.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fermat-test n)&lt;br /&gt;   (define (try-it a)&lt;br /&gt;     (= (expmod a n n) a))&lt;br /&gt;   (try-it (+ 1 (random-integer (- n 1)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Let' start by modifying this procedure so that we pass it the value to test, instead of generating a random value.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fermat-test n a)&lt;br /&gt;   (= (expmod a n n) a))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we just need to define a new procedure that will call this one for every value less than the one we want to test.  If &lt;code&gt;fermat-test&lt;/code&gt; passes for all values tested we should return &lt;code&gt;true&lt;/code&gt;, but if it fails for any value we should return &lt;code&gt;false&lt;/code&gt;.  Here is the complete code listing for the exercise.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;br /&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;br /&gt;(define (expmod base exp m)&lt;br /&gt;   (cond ((= exp 0) 1)&lt;br /&gt;         ((even? exp)&lt;br /&gt;          (remainder (square (expmod base (/ exp 2) m))&lt;br /&gt;                      m))&lt;br /&gt;        (else&lt;br /&gt;          (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;                     m))))&lt;br /&gt;&lt;br /&gt;(define (fermat-test n a)&lt;br /&gt;   (= (expmod a n n) a))&lt;br /&gt;&lt;br /&gt;(define (fermat-full n)&lt;br /&gt;   (define (iter a)&lt;br /&gt;     (cond ((= a 1) #t)&lt;br /&gt;           ((not (fermat-test n a)) #f)&lt;br /&gt;           (else (iter (- a 1)))))&lt;br /&gt;   (iter (- n 1)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Prime numbers will legitimately pass this test, and Carmichael numbers will fool it.  All other composites should fail.  You can test out a few primes and composites in a Scheme interpreter to make sure it works as described.  Here's the output for the first six Carmichael numbers.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (fermat-full 561)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (fermat-full 1105)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (fermat-full 1729)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (fermat-full 2465)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (fermat-full 2821)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (fermat-full 6601)&lt;br /&gt;#t&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-6837804937445619064?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/6837804937445619064/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=6837804937445619064" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6837804937445619064?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6837804937445619064?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-127-carmichael-numbers.html" title="SICP Exercise 1.27: Carmichael numbers" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0EEQHw_cCp7ImA9WxBVGUg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-5201380430423807459</id><published>2010-02-23T15:49:00.007-05:00</published><updated>2010-02-23T16:13:21.248-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-23T16:13:21.248-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.26: Explicit multiplication vs. squaring</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.26&lt;/span&gt; asks us to consider yet another variation on the &lt;code&gt;fast-prime?&lt;/code&gt; procedure from exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-124-fermat-test.html"&gt;1.24&lt;/a&gt;.  This time the &lt;code&gt;expmod&lt;/code&gt; procedure has been modified to use an explicit multiplication instead of calling &lt;code&gt;square&lt;/code&gt;:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (expmod base exp m)&lt;br /&gt;   (cond ((= exp 0) 1)&lt;br /&gt;         ((even? exp)&lt;br /&gt;          (remainder (* (expmod base (/ exp 2) m)&lt;br /&gt;                        (expmod base (/ exp 2) m))&lt;br /&gt;                     m))&lt;br /&gt;         (else&lt;br /&gt;          (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;                     m))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This change causes &lt;code&gt;fast-prime?&lt;/code&gt; to run more slowly than the original &lt;code&gt;prime?&lt;/code&gt; test by transforming the O(log n) process into a O(n) process.  We're asked to explain this transformation.&lt;br /&gt;&lt;br /&gt;A cursory inspection of the code makes it seem like the explicit multiplication will cause twice as many calls to &lt;code&gt;expmod&lt;/code&gt; because each input argument to &lt;code&gt;*&lt;/code&gt; will be evaluated separately, instead of only once when &lt;code&gt;expmod&lt;/code&gt; is passed as the single argument to &lt;code&gt;square&lt;/code&gt;.  This isn't enough to account for the reported slow down.&lt;br /&gt;&lt;br /&gt;Let's take a closer look at the process generated by each version of &lt;code&gt;expmod&lt;/code&gt;.  (Since the only difference between the two versions of &lt;code&gt;expmod&lt;/code&gt; is in the branch where &lt;code&gt;exp&lt;/code&gt; is even, I'm using powers of 2 for that argument to better illustrate the difference in the resulting processes.  I should point out that this is a worst case scenario.)&lt;br /&gt;&lt;br /&gt;Here is what the process generated by the original &lt;code&gt;expmod&lt;/code&gt; procedure using &lt;code&gt;square&lt;/code&gt; might look like:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(expmod 2 8 2)&lt;br /&gt;   (expmod 2 4 2)&lt;br /&gt;       (expmod 2 2 2)&lt;br /&gt;           (expmod 2 1 2)&lt;br /&gt;               (expmod 2 0 2)&lt;br /&gt;               1&lt;br /&gt;           0&lt;br /&gt;       0&lt;br /&gt;   0&lt;br /&gt;0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This is a pretty straightforward linear recursive process.  Now let's look at the process for &lt;code&gt;expmod&lt;/code&gt; when explicit multiplication is used. (This is only part of the process diagram, but it's enough to see what's going on.)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PnLYRqe0k9g/S4RADXPrAXI/AAAAAAAAARk/yJESpD2zwhQ/s1600-h/expmod-mult-diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 152px;" src="http://3.bp.blogspot.com/_PnLYRqe0k9g/S4RADXPrAXI/AAAAAAAAARk/yJESpD2zwhQ/s320/expmod-mult-diagram.png" alt="" id="BLOGGER_PHOTO_ID_5441544676293935474" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Right away, it's easy to see what went wrong here.  By replacing the call to &lt;code&gt;square&lt;/code&gt; with explicit multiplication, we've transformed &lt;code&gt;expmod&lt;/code&gt; from a linear recursive process (like the &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1"&gt;factorial example&lt;/a&gt;) into a tree recursion (like the &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2"&gt;original Fibonacci example&lt;/a&gt;).  This causes the number of recursive calls to &lt;code&gt;expmod&lt;/code&gt; to grow exponentially instead of simply doubling.  What was once a O(log n) process is now O(log 2&lt;sup&gt;n&lt;/sup&gt;), which simplifies to O(n).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-5201380430423807459?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/5201380430423807459/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=5201380430423807459" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5201380430423807459?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5201380430423807459?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-126-explicit.html" title="SICP Exercise 1.26: Explicit multiplication vs. squaring" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_PnLYRqe0k9g/S4RADXPrAXI/AAAAAAAAARk/yJESpD2zwhQ/s72-c/expmod-mult-diagram.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUMFSHs9eyp7ImA9WxBVF0o.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3378009095426777385</id><published>2010-02-21T12:13:00.003-05:00</published><updated>2010-02-21T12:30:19.563-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-21T12:30:19.563-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.25: A closer look at expmod</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.25&lt;/span&gt; asks us to take a closer look at the &lt;code&gt;expmod&lt;/code&gt; procedure that we used in exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-124-fermat-test.html"&gt;1.24&lt;/a&gt; to compute the exponential of a number modulo another number:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (expmod base exp m)&lt;br /&gt;   (cond ((= exp 0) 1)&lt;br /&gt;         ((even? exp)&lt;br /&gt;          (remainder (square (expmod base (/ exp 2) m))&lt;br /&gt;                     m))&lt;br /&gt;         (else&lt;br /&gt;          (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;                     m))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're asked to consider a more straightforward implementation of the same function.  This version makes use of the &lt;code&gt;fast-expt&lt;/code&gt; procedure from section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4"&gt;1.2.4&lt;/a&gt;, which I've also included here.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (expmod base exp m)&lt;br /&gt;   (remainder (fast-expt base exp) m))&lt;br /&gt;&lt;br /&gt;(define (fast-expt b n)&lt;br /&gt;   (cond ((= n 0) 1)&lt;br /&gt;         ((even? n) (square (fast-expt b (/ n 2))))&lt;br /&gt;         (else (* b (fast-expt b (- n 1))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Will this version perform just as well in the fast prime tester from exercise 1.24?  The easiest way to answer that question is to drop it in and test it out.  Starting out with relatively small values, you can see that the new procedure doesn't perform very well at all.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (timed-prime-test 1999)&lt;br /&gt;&lt;br /&gt;1999 *** 138.0&lt;br /&gt;&amp;gt; (timed-prime-test 10007)&lt;br /&gt;&lt;br /&gt;10007 *** 681.0&lt;br /&gt;&amp;gt; (timed-prime-test 100003)&lt;br /&gt;&lt;br /&gt;100003 *** 29059.0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;These values are several orders of magnitude smaller than those used in the previous exercise, but the new procedure is taking a much longer time to complete.  Why is that?&lt;br /&gt;&lt;br /&gt;The answer is buried in a &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#footnote_Temp_78"&gt;footnote to the &lt;code&gt;expmod&lt;/code&gt; code&lt;/a&gt; (#46).&lt;br /&gt;&lt;blockquote&gt;The reduction steps in the cases where the exponent e is greater than 1 are based on the fact that, for any integers x, y, and m, we can find the remainder of x times y modulo m by computing separately the remainders of x modulo m and y modulo m, multiplying these, and then taking the remainder of the result modulo m. For instance, in the case where e is even, we compute the remainder of be/2 modulo m, square this, and take the remainder modulo m. This technique is useful because it means we can perform our computation without ever having to deal with numbers much larger than m.&lt;/blockquote&gt;&lt;br /&gt;The important point is that the original &lt;code&gt;expmod&lt;/code&gt; procedure uses successive squaring to perform its computations &lt;span style="font-weight: bold;"&gt;without ever having to deal with numbers larger than m&lt;/span&gt;.  Simple arithmetic with very large numbers is much slower than arithmetic with 32-bit integers.  That's because the time complexity for arithmetic operations is based on the number of bits in the operands.  The intermediate results during computation in the &lt;code&gt;fast-expt&lt;/code&gt; procedure get very big, very quickly (the final result is growing exponentially, after all).  Since we're only interested in the remainder, modular arithmetic provides a much sleeker solution, as explained in the footnote.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-3378009095426777385?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3378009095426777385/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3378009095426777385" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3378009095426777385?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3378009095426777385?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-125-closer-look-at-expmod.html" title="SICP Exercise 1.25: A closer look at expmod" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUMMQng_cCp7ImA9WxBVF00.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3473658897924895039</id><published>2010-02-20T16:28:00.010-05:00</published><updated>2010-02-20T17:04:43.648-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-20T17:04:43.648-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.24: The Fermat Test</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.24&lt;/span&gt; asks us to once again modify the &lt;code&gt;timed-prime-test&lt;/code&gt; procedure from exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-122-timed-prime-test.html"&gt;1.22&lt;/a&gt;, this time using &lt;code&gt;fast-prime?&lt;/code&gt; (which uses the Fermat test), then test the improvement using the timing statistics we gathered before.&lt;br /&gt;&lt;br /&gt;The Fermat test is a probabilistic method for testing primality, meaning that if a given number passes the Fermat test, the best we can say is that the number is very probably prime.  It's based on &lt;a href="http://mathworld.wolfram.com/FermatsLittleTheorem.html"&gt;Fermat's Little Theorem&lt;/a&gt; which states:&lt;br /&gt;&lt;blockquote&gt;If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.&lt;/blockquote&gt;So to test n for primality, we select a number, a, which is less than n, and raise it to the nth power.  We then divide a&lt;sup&gt;n&lt;/sup&gt; by n to get the remainder.  If n is prime, then the remainder will be equal to a, the base we selected.&lt;br /&gt;&lt;br /&gt;Fermat's Little Theorem says that this property will always hold true if n is prime, but it doesn't say anything about when n isn't prime.  If a&lt;sup&gt;n&lt;/sup&gt; mod n is not equal to a, then we know for certain that n is not prime.  However, there are values of n and a that will pass the Fermat test even when n is not prime.  If we test enough values of a for a given n, we can increase our confidence that n is prime.  Unfortunately, there are extremely rare values of n called &lt;a href="http://mathworld.wolfram.com/CarmichaelNumber.html"&gt;Carmichael numbers&lt;/a&gt; that pass the Fermat test for any value of a.  There are variations on the Fermat test that cannot be fooled.  We'll look at one of those variations, the Miller-Rabin test, in a later exercise.&lt;br /&gt;&lt;br /&gt;The complete code listing below shows what modifications were necessary to use the Fermat test in the &lt;code&gt;timed-prime-test&lt;/code&gt; procedure.  The &lt;code&gt;fast-prime?&lt;/code&gt; procedure takes two arguments, &lt;code&gt;n&lt;/code&gt;, and &lt;code&gt;times&lt;/code&gt;.  The first argument is the number to test, the second argument tells the procedure how many random values to test with.  The more random values we use, the higher our confidence that &lt;code&gt;n&lt;/code&gt; is prime, so we should test a lot of values.  I've (rather arbitrarily) chosen to test 100 random values.&lt;br /&gt;&lt;br /&gt;One other change that you may notice is the inclusion of a library module in the first line of code.  When testing the original code listing from the book, I found that Scheme's primitive &lt;code&gt;random&lt;/code&gt; procedure has a limit of 4,294,967,087.  This won't do for the values we're testing, so I replaced it with the &lt;code&gt;random-integer&lt;/code&gt; procedure, which doesn't have this limitation.  I found out about this procedure and library through the &lt;a href="http://schemecookbook.org/view/Cookbook/NumberRecipeBigRandomNumber"&gt;Scheme Cookbook&lt;/a&gt;.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(require (lib "27.ss" "srfi"))&lt;br /&gt;&lt;br /&gt;(define (timed-prime-test n)&lt;br /&gt;   (newline)&lt;br /&gt;   (display n)&lt;br /&gt;   (start-prime-test n (current-inexact-milliseconds)))&lt;br /&gt;&lt;br /&gt;(define (start-prime-test n start-time)&lt;br /&gt;   (cond ((fast-prime? n 100)&lt;br /&gt;          (report-prime (- (current-inexact-milliseconds) start-time)))))&lt;br /&gt;&lt;br /&gt;(define (report-prime elapsed-time)&lt;br /&gt;   (display " *** ")&lt;br /&gt;   (display elapsed-time))&lt;br /&gt;&lt;br /&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;br /&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;br /&gt;(define (expmod base exp m)&lt;br /&gt;   (cond ((= exp 0) 1)&lt;br /&gt;         ((even? exp)&lt;br /&gt;          (remainder (square (expmod base (/ exp 2) m))&lt;br /&gt;                     m))&lt;br /&gt;         (else&lt;br /&gt;          (remainder (* base (expmod base (- exp 1) m))&lt;br /&gt;                     m))))&lt;br /&gt;&lt;br /&gt;(define (fermat-test n)&lt;br /&gt;   (define (try-it a)&lt;br /&gt;     (= (expmod a n n) a))&lt;br /&gt;   (try-it (+ 1 (random-integer (- n 1)))))&lt;br /&gt;&lt;br /&gt;(define (fast-prime? n times)&lt;br /&gt;   (cond ((= times 0) true)&lt;br /&gt;         ((fermat-test n) (fast-prime? n (- times 1)))&lt;br /&gt;         (else false)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Test Results&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We need to run &lt;code&gt;timed-prime-test&lt;/code&gt; again with the new modifications using the same set of inputs that we found in the previous exercises, then compare the results to see how much we improved the run time.  The following table compares the original data we gathered in exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-122-timed-prime-test.html"&gt;1.22&lt;/a&gt;, the improved algorithm we used in exercise &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-123-improved-prime-test.html"&gt;1.23&lt;/a&gt; (improved  time column), and the new results we got using the Fermat test (all three time columns are in milliseconds).  The ratio column is the ratio of the improved values from exercise 1.23 to the fermat time column.&lt;br /&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table style="border-color: gray; border-width: 1px;"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;th&gt; prime &lt;/th&gt;&lt;th&gt; original time &lt;/th&gt;&lt;th&gt; improved time &lt;/th&gt;&lt;th&gt; fermat time &lt;/th&gt;&lt;th&gt; ratio &lt;/th&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000019&lt;/td&gt;&lt;td&gt;141&lt;/td&gt;&lt;td&gt;103&lt;/td&gt;&lt;td&gt;178&lt;/td&gt;&lt;td&gt;0.58&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000033&lt;/td&gt;&lt;td&gt;172&lt;/td&gt;&lt;td&gt;101&lt;/td&gt;&lt;td&gt;187&lt;/td&gt;&lt;td&gt;0.54&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000061&lt;/td&gt;&lt;td&gt;154&lt;/td&gt;&lt;td&gt;112&lt;/td&gt;&lt;td&gt;173&lt;/td&gt;&lt;td&gt;0.65&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000003&lt;/td&gt;&lt;td&gt;516&lt;/td&gt;&lt;td&gt;310&lt;/td&gt;&lt;td&gt;181&lt;/td&gt;&lt;td&gt;1.71&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000019&lt;/td&gt;&lt;td&gt;493&lt;/td&gt;&lt;td&gt;295&lt;/td&gt;&lt;td&gt;186&lt;/td&gt;&lt;td&gt;1.59&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000057&lt;/td&gt;&lt;td&gt;527&lt;/td&gt;&lt;td&gt;305&lt;/td&gt;&lt;td&gt;189&lt;/td&gt;&lt;td&gt;1.61&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000039&lt;/td&gt;&lt;td&gt;1627&lt;/td&gt;&lt;td&gt;861&lt;/td&gt;&lt;td&gt;189&lt;/td&gt;&lt;td&gt;4.56&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000061&lt;/td&gt;&lt;td&gt;1559&lt;/td&gt;&lt;td&gt;884&lt;/td&gt;&lt;td&gt;195&lt;/td&gt;&lt;td&gt;4.53&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000063&lt;/td&gt;&lt;td&gt;1549&lt;/td&gt;&lt;td&gt;873&lt;/td&gt;&lt;td&gt;197&lt;/td&gt;&lt;td&gt;4.43&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000037&lt;/td&gt;&lt;td&gt;5014&lt;/td&gt;&lt;td&gt;2671&lt;/td&gt;&lt;td&gt;208&lt;/td&gt;&lt;td&gt;12.84&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000051&lt;/td&gt;&lt;td&gt;4932&lt;/td&gt;&lt;td&gt;2668&lt;/td&gt;&lt;td&gt;211&lt;/td&gt;&lt;td&gt;12.64&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000099&lt;/td&gt;&lt;td&gt;4855&lt;/td&gt;&lt;td&gt;2697&lt;/td&gt;&lt;td&gt;208&lt;/td&gt;&lt;td&gt;12.97&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000031&lt;/td&gt;&lt;td&gt;15745&lt;/td&gt;&lt;td&gt;8531&lt;/td&gt;&lt;td&gt;233&lt;/td&gt;&lt;td&gt;36.61&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000067&lt;/td&gt;&lt;td&gt;16022&lt;/td&gt;&lt;td&gt;8264&lt;/td&gt;&lt;td&gt;231&lt;/td&gt;&lt;td&gt;35.77&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000097&lt;/td&gt;&lt;td&gt;15861&lt;/td&gt;&lt;td&gt;8530&lt;/td&gt;&lt;td&gt;225&lt;/td&gt;&lt;td&gt;37.91&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000037&lt;/td&gt;&lt;td&gt;48950&lt;/td&gt;&lt;td&gt;26346&lt;/td&gt;&lt;td&gt;244&lt;/td&gt;&lt;td&gt;108.0&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000091&lt;/td&gt;&lt;td&gt;48836&lt;/td&gt;&lt;td&gt;26210&lt;/td&gt;&lt;td&gt;255&lt;/td&gt;&lt;td&gt;102.8&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000159&lt;/td&gt;&lt;td&gt;49008&lt;/td&gt;&lt;td&gt;26256&lt;/td&gt;&lt;td&gt;257&lt;/td&gt;&lt;td&gt;102.2&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Analysis&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The timing numbers from the Fermat test start out looking pretty poor compared to what we've seen previously.  This has mostly to do with the completely arbitrary number of random values I chose to test each prime with.  As we increase the size of the numbers we're testing, you can see that the time using the Fermat test barely increases at all.  We can verify that the time increase is logarithmic by observing that as the numbers under test increase by a factor of 10, the ratio column increases by a factor of roughly three.  This logarithmic characteristic is due to the fact that the &lt;code&gt;expmod&lt;/code&gt; procedure used in &lt;code&gt;fermat-test&lt;/code&gt; has a logarithmic time complexity.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-3473658897924895039?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3473658897924895039/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3473658897924895039" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3473658897924895039?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3473658897924895039?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-124-fermat-test.html" title="SICP Exercise 1.24: The Fermat Test" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CE8CQn89cCp7ImA9WxBVEkg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8459049333959400676</id><published>2010-02-14T22:44:00.015-05:00</published><updated>2010-02-15T11:54:23.168-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-15T11:54:23.168-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzles" /><category scheme="http://www.blogger.com/atom/ns#" term="chess" /><category scheme="http://www.blogger.com/atom/ns#" term="logic" /><title>Solution to A Curiously Clever Chess Puzzle</title><content type="html">In &lt;a href="http://www.billthelizard.com/2010/02/curiously-clever-chess-puzzle.html"&gt;yesterday's post&lt;/a&gt; I asked two questions about the following chess position.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s1600-h/curious_chess_puzzle.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 288px; height: 288px;" src="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s320/curious_chess_puzzle.jpg" alt="" id="BLOGGER_PHOTO_ID_5438295487401412290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;First, how is this a legal position, and second, how can white guarantee a checkmate in four moves or fewer?&lt;br /&gt;&lt;br /&gt;This puzzle is much more commonly known as &lt;span style="font-style: italic;"&gt;Lord Dunsany's Chess Problem&lt;/span&gt;, although &lt;a href="http://alangullette.com/lit/dunsany/chess/problems.htm"&gt;he had several others&lt;/a&gt;.  I first ran across this particular problem by Lord Dunsany in Martin Gardner's &lt;a href="http://books.google.com/books?id=sUuBCzazfYUC&amp;amp;printsec=frontcover#v=onepage&amp;amp;q=&amp;amp;f=false"&gt;My Best Mathematical and Logic Puzzles&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'll let Mr. Gardner explain the first part of the puzzle:&lt;br /&gt;&lt;blockquote&gt;The key to Lord Dunsany's chess problem is the fact that the black queen is not on a black square as she must be at the start of a game.  This means that the black king and queen have moved, and this could have happened only if some black pawns have moved.  Pawns cannot move backward, so we are forced to conclude that the black pawns reached their present positions from the other side of the board!  With this in mind, it is easy to discover that the white knight on the right has an easy mate in four moves.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;If that seems like a dirty, dirty trick to you, that's because it is.  Chess diagrams are traditionally drawn from the perspective of the white player (white pieces at the bottom of the diagram in the starting position), so this puzzle really forces you to check your assumptions and "think outside the box."&lt;br /&gt;&lt;br /&gt;As Gardner mentioned, the mate in four is easy once you've mentally turned the board around.  First, white moves his knight in front of his king, threatening mate in two more moves.  Black can delay white's plan by one move by moving his own knight out into the bishop's file.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PnLYRqe0k9g/S3jO5BQXp8I/AAAAAAAAARU/QobRvnHGGTQ/s1600-h/curious_chess_puzzle_2.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 288px; height: 288px;" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/S3jO5BQXp8I/AAAAAAAAARU/QobRvnHGGTQ/s320/curious_chess_puzzle_2.jpg" alt="" id="BLOGGER_PHOTO_ID_5438324029034833858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;When white advances his knight on the bishop's file, black can protect the mating square with his own knight.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PnLYRqe0k9g/S3jP5JRI2sI/AAAAAAAAARc/6kbb3qC6fXA/s1600-h/curious_chess_puzzle_3.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 288px; height: 288px;" src="http://3.bp.blogspot.com/_PnLYRqe0k9g/S3jP5JRI2sI/AAAAAAAAARc/6kbb3qC6fXA/s320/curious_chess_puzzle_3.jpg" alt="" id="BLOGGER_PHOTO_ID_5438325130697169602" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Next, white can capture the knight with his queen.  After that, black is defenseless to stop the white knight from delivering checkmate on the fourth move.  The black king is hemmed in by his own pieces.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;All chess diagrams are courtesy of the &lt;a href="http://www.apronus.com/chess/wbeditor.php"&gt;Online Chess Diagram Editor&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8459049333959400676?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8459049333959400676/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8459049333959400676" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8459049333959400676?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8459049333959400676?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/solution-to-curiously-clever-chess.html" title="Solution to A Curiously Clever Chess Puzzle" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s72-c/curious_chess_puzzle.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;CUEMRnk6fyp7ImA9WxBVEkQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-7531519325059174805</id><published>2010-02-14T21:32:00.007-05:00</published><updated>2010-02-15T23:14:47.717-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-15T23:14:47.717-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzles" /><category scheme="http://www.blogger.com/atom/ns#" term="chess" /><category scheme="http://www.blogger.com/atom/ns#" term="logic" /><title>A Curiously Clever Chess Puzzle</title><content type="html">It's been some time since I've posted any logic puzzles, and I don't remember &lt;span style="font-style: italic;"&gt;ever &lt;/span&gt;posting a chess puzzle, so today I'll kill two birds with one stone.  In fact, the following position represents two puzzles in one.  (You don't have to be a grandmaster at chess to solve it, so even if you only know the basic rules of the game you should give it a try.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s1600-h/curious_chess_puzzle.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 288px; height: 288px;" src="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s320/curious_chess_puzzle.jpg" alt="" id="BLOGGER_PHOTO_ID_5438295487401412290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first part of the puzzle requires more logical thinking than chess skill.  Explain how this highly unlikely position could possibly be reached in a game.  You don't have to show all the moves, but you should be able to convince yourself that it &lt;span style="font-style: italic;"&gt;is &lt;/span&gt;a legal position.&lt;br /&gt;&lt;br /&gt;Second, it's white's turn to move.  Show how white can checkmate black in at most four moves.&lt;br /&gt;&lt;br /&gt;I'll give the answer and the original source of this puzzle in an upcoming post.  (&lt;span style="font-weight: bold;"&gt;Update&lt;/span&gt;: the &lt;a href="http://www.billthelizard.com/2010/02/solution-to-curiously-clever-chess.html"&gt;full solution&lt;/a&gt; is up.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;The diagram image is courtesy of the &lt;a href="http://www.apronus.com/chess/wbeditor.php"&gt;Online Chess Diagram Editor&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-7531519325059174805?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/7531519325059174805/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=7531519325059174805" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7531519325059174805?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7531519325059174805?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/curiously-clever-chess-puzzle.html" title="A Curiously Clever Chess Puzzle" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_PnLYRqe0k9g/S3i07rYrxsI/AAAAAAAAARM/VTOml0xXyQ0/s72-c/curious_chess_puzzle.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">8</thr:total></entry><entry gd:etag="W/&quot;CkQHR3o_cCp7ImA9WxBWFko.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-2560158303452336259</id><published>2010-02-08T17:02:00.005-05:00</published><updated>2010-02-08T18:05:36.448-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-08T18:05:36.448-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.23: Improved Prime Test</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.23&lt;/span&gt; asks us to add a modification to the &lt;code&gt;smallest-divisor&lt;/code&gt; procedure, then test the improvement using the timing statistics we gathered in &lt;a href="http://www.billthelizard.com/2010/02/sicp-exercise-122-timed-prime-test.html"&gt;exercise 1.22&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We start with the observation that &lt;code&gt;smallest-divisor&lt;/code&gt; inefficiently finds the divisor of n by checking &lt;span style="font-style: italic;"&gt;every&lt;/span&gt; candidate value from 2 to √n.  The number of candidates can easily be cut nearly in half by simply not checking even numbers greater than 2.&lt;br /&gt;&lt;br /&gt;Our first task is to define a procedure &lt;code&gt;next&lt;/code&gt; that returns 3 if its input is equal to 2 and otherwise returns its input plus 2.  The code is as straightforward as the description:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (next x)&lt;br /&gt;  (if (= x 2) 3 (+ x 2)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Our next task is to modify the &lt;code&gt;find-divisor&lt;/code&gt; procedure to use &lt;code&gt;(next test-divisor)&lt;/code&gt; instead of &lt;code&gt;(+ test-divisor 1)&lt;/code&gt;.  This is a straight substitution, and no other changes to the code from exercise 1.22 are necessary.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (find-divisor n test-divisor)&lt;br /&gt;  (cond ((&amp;gt; (square test-divisor) n) n)&lt;br /&gt;        ((divides? test-divisor n) test-divisor)&lt;br /&gt;        (else (find-divisor n (next test-divisor)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Finally, we need to run &lt;code&gt;timed-prime-test&lt;/code&gt; with these modifications using the same set of inputs that we found in the previous exercise, then compare the results to see if we really did cut the run time in half.  The following table compares the original data to new timing data gathered using the improved algorithm.  (Values in the new time column are averaged from three runs of the procedure.)&lt;br /&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table style="border-color: gray; border-width: 1px;"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;th&gt; prime &lt;/th&gt;&lt;th&gt; old time (ms) &lt;/th&gt;&lt;th&gt; new time (ms) &lt;/th&gt;&lt;th&gt; ratio &lt;/th&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000019&lt;/td&gt;&lt;td&gt;141&lt;/td&gt;&lt;td&gt;103&lt;/td&gt;&lt;td&gt;1.37&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000033&lt;/td&gt;&lt;td&gt;172&lt;/td&gt;&lt;td&gt;101&lt;/td&gt;&lt;td&gt;1.70&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000061&lt;/td&gt;&lt;td&gt;154&lt;/td&gt;&lt;td&gt;112&lt;/td&gt;&lt;td&gt;1.38&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000003&lt;/td&gt;&lt;td&gt;516&lt;/td&gt;&lt;td&gt;310&lt;/td&gt;&lt;td&gt;1.67&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000019&lt;/td&gt;&lt;td&gt;493&lt;/td&gt;&lt;td&gt;295&lt;/td&gt;&lt;td&gt;1.67&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000057&lt;/td&gt;&lt;td&gt;527&lt;/td&gt;&lt;td&gt;305&lt;/td&gt;&lt;td&gt;1.73&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000039&lt;/td&gt;&lt;td&gt;1627&lt;/td&gt;&lt;td&gt;861&lt;/td&gt;&lt;td&gt;1.89&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000061&lt;/td&gt;&lt;td&gt;1559&lt;/td&gt;&lt;td&gt;884&lt;/td&gt;&lt;td&gt;1.76&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000063&lt;/td&gt;&lt;td&gt;1549&lt;/td&gt;&lt;td&gt;873&lt;/td&gt;&lt;td&gt;1.77&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000037&lt;/td&gt;&lt;td&gt;5014&lt;/td&gt;&lt;td&gt;2671&lt;/td&gt;&lt;td&gt;1.88&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000051&lt;/td&gt;&lt;td&gt;4932&lt;/td&gt;&lt;td&gt;2668&lt;/td&gt;&lt;td&gt;1.85&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10000000000099&lt;/td&gt;&lt;td&gt;4855&lt;/td&gt;&lt;td&gt;2697&lt;/td&gt;&lt;td&gt;1.80&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000031&lt;/td&gt;&lt;td&gt;15745&lt;/td&gt;&lt;td&gt;8531&lt;/td&gt;&lt;td&gt;1.85&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000067&lt;/td&gt;&lt;td&gt;16022&lt;/td&gt;&lt;td&gt;8264&lt;/td&gt;&lt;td&gt;1.94&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;100000000000097&lt;/td&gt;&lt;td&gt;15861&lt;/td&gt;&lt;td&gt;8530&lt;/td&gt;&lt;td&gt;1.86&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000037&lt;/td&gt;&lt;td&gt;48950&lt;/td&gt;&lt;td&gt;26346&lt;/td&gt;&lt;td&gt;1.86&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000091&lt;/td&gt;&lt;td&gt;48836&lt;/td&gt;&lt;td&gt;26210&lt;/td&gt;&lt;td&gt;1.86&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1000000000000159&lt;/td&gt;&lt;td&gt;49008&lt;/td&gt;&lt;td&gt;26256&lt;/td&gt;&lt;td&gt;1.87&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Analysis&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We're seeing a clear improvement in the new procedure, but it's not quite as fast as we expected.  The first thing that needs to be explained in this data is the fact that the first three values shows very little performance gain, the next three a little more, then fairly consistent results for the remaining data.  I think this can be explained by other processes running on the computer.  Measuring shorter runs of the procedure (those in the 100-500 millisecond range) is going to be much more sensitive to measurement error due to being interrupted by background processes.  These errors will be a less significant proportion of the total run time for longer runs of the procedure.&lt;br /&gt;&lt;br /&gt;We're also seeing that the procedure is only running approximately 1.85 times as fast, instead of the expected factor of 2.  This may be explained by the fact that we replaced a primitive operation, &lt;code&gt;(+ test-divisor 1)&lt;/code&gt;, by a user-defined operation, &lt;code&gt;(next test-divisor)&lt;/code&gt;.   Each time that user-defined operation is called, an extra &lt;code&gt;if&lt;/code&gt; must be evaluated (to check if the input is 2).  Other than this small discrepancy, I think the improvement is quite good for such a small change to the code.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-2560158303452336259?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/2560158303452336259/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=2560158303452336259" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2560158303452336259?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2560158303452336259?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-123-improved-prime-test.html" title="SICP Exercise 1.23: Improved Prime Test" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A04CRH86fyp7ImA9WxBUEE8.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-78531014571407286</id><published>2010-02-05T17:36:00.018-05:00</published><updated>2010-02-24T11:46:05.117-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-24T11:46:05.117-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.22: Timed Prime Test</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.22&lt;/span&gt; introduces a new primitive called &lt;code&gt;runtime&lt;/code&gt;...&lt;br /&gt;&lt;blockquote&gt;Most Lisp implementations include a primitive called runtime that returns an integer that specifies the amount of time the system has been running (measured, for example, in microseconds).&lt;/blockquote&gt;&lt;br /&gt;Unfortunately, this turns out not to be the case for Scheme.  After a bit of research, I found what I think to be a suitable replacement: &lt;a href="http://docs.plt-scheme.org/reference/time.html#%28def._%28%28quote._%7E23%7E25kernel%29._current-inexact-milliseconds%29%29"&gt;current-inexact-milliseconds&lt;/a&gt;.  It's not as precise as I'd like, but there are a couple of workarounds to this problem that I'll explain shortly.&lt;br /&gt;&lt;br /&gt;The exercise goes on to to introduce the &lt;code&gt;timed-prime-test&lt;/code&gt; procedure, which prints its input &lt;code&gt;n&lt;/code&gt; and tests to see if &lt;code&gt;n&lt;/code&gt; is prime.  If &lt;code&gt;n&lt;/code&gt; is prime, the procedure prints three asterisks followed by the amount of time used in performing the test.  Here is the modified version that I'll be using, including all of the required support procedures from the book:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (timed-prime-test n)&lt;br /&gt;   (newline)&lt;br /&gt;   (display n)&lt;br /&gt;   (start-prime-test n (current-inexact-milliseconds)))&lt;br /&gt;&lt;br /&gt;(define (start-prime-test n start-time)&lt;br /&gt;   (cond ((prime? n)&lt;br /&gt;          (report-prime (- (current-inexact-milliseconds) start-time)))))&lt;br /&gt;&lt;br /&gt;(define (report-prime elapsed-time)&lt;br /&gt;   (display " *** ")&lt;br /&gt;   (display elapsed-time))&lt;br /&gt;&lt;br /&gt;(define (smallest-divisor n)&lt;br /&gt;   (find-divisor n 2))&lt;br /&gt;&lt;br /&gt;(define (find-divisor n test-divisor)&lt;br /&gt;   (cond ((&amp;gt; (square test-divisor) n) n)&lt;br /&gt;         ((divides? test-divisor n) test-divisor)&lt;br /&gt;         (else (find-divisor n (+ test-divisor 1)))))&lt;br /&gt;&lt;br /&gt;(define (divides? a b)&lt;br /&gt;   (= (remainder b a) 0))&lt;br /&gt;&lt;br /&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;br /&gt;(define (prime? n)&lt;br /&gt;   (= n (smallest-divisor n)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Our task (finally) is to use &lt;code&gt;timed-prime-test&lt;/code&gt; to  write a procedure named &lt;code&gt;search-for-primes&lt;/code&gt; that checks the primality of consecutive odd integers in a specified range.  We're instructed to use this procedure to find the three smallest primes larger than 1000, 10000, 100000, and 1000000.  Since the &lt;code&gt;prime?&lt;/code&gt; procedure has an order of growth of O(√n), we should expect a run time increase of a factor of √10 at each step.  We'll use the output from &lt;code&gt;timed-prime-test&lt;/code&gt; to check this assumption.&lt;br /&gt;&lt;br /&gt;The following procedure checks the primality of consecutive odd integers in the range from start to end.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (search-for-primes start end)&lt;br /&gt;   (if (even? start)&lt;br /&gt;       (search-for-primes (+ start 1) end)&lt;br /&gt;       (cond ((&amp;lt; start end) (timed-prime-test start)&lt;br /&gt;                            (search-for-primes (+ start 2) end)))))&lt;br /&gt;&lt;br /&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The procedure initially checks to see if the &lt;code&gt;start&lt;/code&gt; input argument is even.  If it is, the procedure simply starts over with the next (odd) integer.  Next the procedure checks to see if &lt;code&gt;start&lt;/code&gt; is less than &lt;code&gt;end&lt;/code&gt;.  If so, it performs a &lt;code&gt;timed-prime-test&lt;/code&gt; on &lt;code&gt;start&lt;/code&gt;, then recursively calls itself with the next odd integer as a starting value.  This process will continue until &lt;code&gt;start&lt;/code&gt; exceeds &lt;code&gt;end&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;With a little bit of trial and error we can find &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; values that surround the first three primes larger than our target values.  Here's a sample run starting at 1000.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (search-for-primes 1000 1020)&lt;br /&gt;&lt;br /&gt;1001&lt;br /&gt;1003&lt;br /&gt;1005&lt;br /&gt;1007&lt;br /&gt;1009 *** 1.0&lt;br /&gt;1011&lt;br /&gt;1013 *** 1.0&lt;br /&gt;1015&lt;br /&gt;1017&lt;br /&gt;1019 *** 0.0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can tell from this output that our timer's resolution isn't fine enough to give us meaningful results on modern desktop hardware (even if it is cheap).  I see two things we can do to work around this problem.  First, we could ignore the suggested inputs from the exercise and just keep increasing the input values until we get meaningful measurements.  Second, we could run &lt;code&gt;prime?&lt;/code&gt; in a loop and measure how long it takes to test a value 1000 (or maybe more) times.  The code is ready as-is for the first option, so that's what I'm going to try.  (If anyone implements the second option, please leave a comment so we can compare results.)&lt;br /&gt;&lt;br /&gt;The first consistent results I got were by using a &lt;code&gt;start&lt;/code&gt; value of 10&lt;sup&gt;10&lt;/sup&gt;.  It took an average of 154 milliseconds to test each of the first three primes after that value.  The following table shows details of the time required to test the primality of numbers spread over several orders of magnitude.&lt;br /&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table style="border-color: gray; border-width: 1px;"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;th&gt; start &lt;/th&gt;&lt;th&gt; primes &lt;/th&gt;&lt;th&gt; time(ms) &lt;/th&gt;&lt;th&gt; avg time(ms) &lt;/th&gt;&lt;th&gt; ratio &lt;/th&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;10&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;10000000019&lt;/td&gt;&lt;br /&gt; &lt;td&gt;141&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;155.67&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; - &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;10000000033&lt;/td&gt;&lt;br /&gt; &lt;td&gt;172&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;10000000061&lt;/td&gt;&lt;br /&gt; &lt;td&gt;154&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;11&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;100000000003&lt;/td&gt;&lt;br /&gt; &lt;td&gt;516&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;512&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; 3.289 &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;100000000019&lt;/td&gt;&lt;br /&gt; &lt;td&gt;493&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;100000000057&lt;/td&gt;&lt;br /&gt; &lt;td&gt;527&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;12&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;1000000000039&lt;/td&gt;&lt;br /&gt; &lt;td&gt;1627&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;1578.33&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; 3.082 &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;1000000000061&lt;/td&gt;&lt;br /&gt; &lt;td&gt;1559&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;1000000000063&lt;/td&gt;&lt;br /&gt; &lt;td&gt;1549&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;13&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;10000000000037&lt;/td&gt;&lt;br /&gt; &lt;td&gt;5014&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;4933.67&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; 3.126 &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;10000000000051&lt;/td&gt;&lt;br /&gt; &lt;td&gt;4932&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;10000000000099&lt;/td&gt;&lt;br /&gt; &lt;td&gt;4855&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;14&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;100000000000031&lt;/td&gt;&lt;br /&gt; &lt;td&gt;15745&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;15876&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; 3.218 &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;100000000000067&lt;/td&gt;&lt;br /&gt; &lt;td&gt;16022&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;100000000000097&lt;/td&gt;&lt;br /&gt; &lt;td&gt;15861&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;10&lt;sup&gt;15&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt; &lt;td&gt;1000000000000037&lt;/td&gt;&lt;br /&gt; &lt;td&gt;48950&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt;48931.33&lt;/td&gt;&lt;br /&gt; &lt;td rowspan="3"&gt; 3.082 &lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;1000000000000091&lt;/td&gt;&lt;br /&gt; &lt;td&gt;48836&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt; &lt;td&gt;1000000000000159&lt;/td&gt;&lt;br /&gt; &lt;td&gt;49008&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The last column shows the ratio of the average time for each row to the average time for the preceding row.  These ratios stay very close to √10, which is approximately 3.162.  These results do seem to verify that programs on my machine run in time proportional to the number of steps required for the computation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-78531014571407286?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/78531014571407286/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=78531014571407286" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/78531014571407286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/78531014571407286?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/sicp-exercise-122-timed-prime-test.html" title="SICP Exercise 1.22: Timed Prime Test" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;A0ECQ3g7fip7ImA9WxBWFE0.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-551650746436931540</id><published>2010-02-01T17:11:00.001-05:00</published><updated>2010-02-05T17:41:02.606-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-05T17:41:02.606-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mersenne" /><category scheme="http://www.blogger.com/atom/ns#" term="perfect numbers" /><category scheme="http://www.blogger.com/atom/ns#" term="unsolved" /><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>Unsolved: Perfect Numbers and Mersenne Primes</title><content type="html">In an earlier post I talked about perfect numbers, and how it was still unknown whether there are any &lt;a href="http://www.billthelizard.com/2010/01/unsolved-odd-perfect-numbers.html"&gt;odd perfect numbers&lt;/a&gt;.  There's another unsolved problem surrounding the perfect numbers, and this one intersects with a special set of numbers that you may have heard of, the Mersenne primes.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Mersenne numbers and Mersenne primes&lt;/h4&gt;Mersenne numbers take their name from the French monk and mathematician &lt;a href="http://en.wikipedia.org/wiki/Marin_Mersenne"&gt;Father Marin Mersenne&lt;/a&gt;, even though they were studied as long ago as the times of &lt;a href="http://en.wikipedia.org/wiki/Euclid"&gt;Euclid&lt;/a&gt;.  You construct Mersenne numbers by subtracting 1 from a power of 2.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;M&lt;sub&gt;n&lt;/sub&gt; = 2&lt;sup&gt;n&lt;/sup&gt; - 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The following table details the construction of the first sixteen Mersenne numbers.&lt;br /&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table style="border-color: gray; border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt; n &lt;/th&gt;&lt;th&gt; 2&lt;sup&gt;n&lt;/sup&gt; &lt;/th&gt;&lt;th&gt; 2&lt;sup&gt;n&lt;/sup&gt; - 1 &lt;/th&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;2&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;3&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;7&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;5&lt;/td&gt;&lt;td&gt;32&lt;/td&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;31&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;63&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;7&lt;/td&gt;&lt;td&gt;128&lt;/td&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;127&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;td&gt;255&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;512&lt;/td&gt;&lt;td&gt;511&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;1024&lt;/td&gt;&lt;td&gt;1023&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;11&lt;/td&gt;&lt;td&gt;2048&lt;/td&gt;&lt;td&gt;2047&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;4096&lt;/td&gt;&lt;td&gt;4095&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;13&lt;/td&gt;&lt;td&gt;8192&lt;/td&gt;&lt;td style="background-color: rgb(218, 238, 218);"&gt;8191&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;16384&lt;/td&gt;&lt;td&gt;16383&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;32768&lt;/td&gt;&lt;td&gt;32767&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;65536&lt;/td&gt;&lt;td&gt;65535&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;If you look closely at the highlighted fields you may notice what mathematicians have known for centuries.  A Mersenne number (2&lt;sup&gt;n&lt;/sup&gt; - 1) cannot be prime unless the exponent n is prime.  This is often expressed with a slightly different notation.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;M&lt;sub&gt;p&lt;/sub&gt; = 2&lt;sup&gt;p&lt;/sup&gt; - 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;What wasn't known in the time of the ancient Greeks was whether or not the exponent being prime meant that M&lt;sub&gt;p&lt;/sub&gt; would &lt;span style="font-style: italic;"&gt;always&lt;/span&gt; be prime.  It wasn't until the 16th century, when it was discovered that 2&lt;sup&gt;11&lt;/sup&gt; - 1 = 2047 is &lt;span style="font-style: italic;"&gt;not &lt;/span&gt;prime, that this question was finally settled (2047 = 23 * 89).  In order for M&lt;sub&gt;p&lt;/sub&gt; to be prime, it is &lt;span style="font-style: italic;"&gt;necessary but not sufficient&lt;/span&gt; for the exponent p to also be prime.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Constructing Perfect Numbers&lt;/h4&gt;Perfect numbers have also been studied since the times of the early Greek mathematicians.  It was Euclid who first discovered that the first four perfect numbers are given by the formula&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;P = 2&lt;sup&gt;p-1&lt;/sup&gt; * (2&lt;sup&gt;p&lt;/sup&gt; - 1)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;6 = 2&lt;sup&gt;1&lt;/sup&gt; * (2&lt;sup&gt;2&lt;/sup&gt; - 1)&lt;br /&gt;28 = 2&lt;sup&gt;2&lt;/sup&gt; * (2&lt;sup&gt;3&lt;/sup&gt; - 1)&lt;br /&gt;496 = 2&lt;sup&gt;4&lt;/sup&gt; * (2&lt;sup&gt;5&lt;/sup&gt; - 1)&lt;br /&gt;8128 = 2&lt;sup&gt;6&lt;/sup&gt; * (2&lt;sup&gt;7&lt;/sup&gt; - 1)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;It wasn't until 1849 that it was shown by Euler (in a paper published after his death) that all even perfect numbers are of the form 2&lt;sup&gt;p-1&lt;/sup&gt; * (2&lt;sup&gt;p&lt;/sup&gt; - 1), where (2&lt;sup&gt;p&lt;/sup&gt; - 1) is a Mersenne prime.&lt;br /&gt;&lt;br /&gt;Since every even perfect number corresponds to a Mersenne prime (and vice versa), searching for perfect numbers is the same as searching for Mersenne primes.  This leads us to two unsolved problems.&lt;br /&gt;&lt;br /&gt;&lt;div style="border: 1px solid rgb(153, 153, 153); padding: 15px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); width: 90%;"&gt;It isn't known if there are infinitely many even perfect numbers.&lt;/div&gt;&lt;br /&gt;&lt;div style="border: 1px solid rgb(153, 153, 153); padding: 15px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); width: 90%;"&gt;It isn't known if there are infinitely many Mersenne primes.&lt;/div&gt;&lt;br /&gt;(In fact, given the 1-to-1 correspondence between even perfect numbers and Mersenne primes, it really wouldn't be incorrect to say that either one of these problems is just a restatement of the other.)&lt;br /&gt;&lt;br /&gt;The largest prime number yet discovered as of this writing is the Mersenne prime 2&lt;sup&gt;43,112,609&lt;/sup&gt; - 1, which has a starggering 12,978,189 digits.  The corresponding perfect number, 2&lt;sup&gt;43,112,608&lt;/sup&gt; * (2&lt;sup&gt;43,112,609&lt;/sup&gt; - 1), has 25,956,377 digits.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Additional reading&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this article I've barely scratched the surface of prime number research.  There is a very large network of people and computers dedicated to the search for Mersenne primes.  For more information (and to possibly join in the search) have a look at the &lt;a href="http://www.mersenne.org/"&gt;Great Internet Mersenne Prime Search&lt;/a&gt; (GIMPS).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-551650746436931540?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/551650746436931540/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=551650746436931540" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/551650746436931540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/551650746436931540?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/02/unsolved-perfect-numbers-and-mersenne.html" title="Unsolved: Perfect Numbers and Mersenne Primes" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0IFQncyfCp7ImA9WxBXGUk.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-4974120842170790372</id><published>2010-01-30T12:34:00.004-05:00</published><updated>2010-01-31T09:51:53.994-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-31T09:51:53.994-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="misc" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><category scheme="http://www.blogger.com/atom/ns#" term="links" /><category scheme="http://www.blogger.com/atom/ns#" term="interesting" /><title>Interesting Miscellany</title><content type="html">Here are some of the links I've found interesting enough to &lt;a href="http://twitter.com/lizardbill"&gt;tweet or retweet&lt;/a&gt; in that past several weeks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Programming&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.cise.ufl.edu/%7Emanuel/obfuscate/pi.c"&gt;A beautiful obfuscated Pi calculator&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;Programming language trends of 2009&lt;/a&gt;&lt;br /&gt;&lt;span class="status-body"&gt;&lt;span class="entry-content"&gt;&lt;a href="http://blogs.mathworks.com/loren/2010/01/19/mathematical-recreations-tweetable-game-of-life/"&gt;Tweetable game of life in MATLAB&lt;/a&gt;&lt;br /&gt;&lt;a href="https://documents.epfl.ch/users/l/le/lenstra/public/papers/rsa768.txt"&gt;Factorization of RSA768&lt;/a&gt;&lt;br /&gt;&lt;a href="http://programmingpraxis.com/2010/01/12/calculating-sines/"&gt;Calculating Sines&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Science&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.cenedella.com/stone/archives/2010/01/leonardo_da_vincis_resume.html"&gt;Leonardo da Vinci's resume&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ted.com/talks/richard_dawkins_growing_up_in_the_universe.html"&gt;Richard Dawkins: Growing up in the universe&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.cs.virginia.edu/%7Erobins/YouAndYourResearch.html"&gt;Richard Hamming: You and your research&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Math&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.diovo.com/2010/01/a-quick-little-puzzle/"&gt;A quick little puzzle&lt;/a&gt; (in probability)&lt;br /&gt;&lt;a href="http://www.maa.org/awards/eulerbook.html"&gt;Euler Book Prize&lt;/a&gt; (A list to watch in the future.  Since the site isn't updated for 2010 yet, the winner was &lt;a href="http://press.princeton.edu/titles/8722.html"&gt;Euler's Gem&lt;/a&gt; by David S. Richeson.)&lt;br /&gt;&lt;a href="http://sfbart.posterous.com/cryptic-math-ad-explained"&gt;A cryptic math advertisement&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Miscellaneous&lt;/span&gt;&lt;br /&gt;&lt;a href="http://succeedblog.org/"&gt;Succed Blog&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.tomshardware.com/news/imperva-rockyou-most-common-passwords,9486.html"&gt;RockYou.com's 20 most common passwords&lt;/a&gt;&lt;br /&gt;&lt;a href="http://insidetech.monster.com/benefits/articles/2818-50-books-every-geek-should-read"&gt;50 Books Every Geek Should Read&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-4974120842170790372?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/4974120842170790372/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=4974120842170790372" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4974120842170790372?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4974120842170790372?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/interesting-miscellany.html" title="Interesting Miscellany" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CUUFQH0_fSp7ImA9WxBXGEs.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8706828198767451043</id><published>2010-01-30T09:44:00.004-05:00</published><updated>2010-01-30T09:53:31.345-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-30T09:53:31.345-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.21: Smallest Divisor</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.6"&gt;1.2.6  Example: Testing for Primality&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.21&lt;/span&gt; asks us to use the &lt;code&gt;smallest-divisor&lt;/code&gt; procedure to find the smallest divisor of each of the following numbers: 199, 1999, 19999.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;smallest-divisor&lt;/code&gt; procedure was given earlier in the section.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (smallest-divisor n)&lt;br /&gt;   (find-divisor n 2))&lt;br /&gt;&lt;br /&gt;(define (find-divisor n test-divisor)&lt;br /&gt;   (cond ((&amp;gt; (square test-divisor) n) n)&lt;br /&gt;         ((divides? test-divisor n) test-divisor)&lt;br /&gt;         (else (find-divisor n (+ test-divisor 1)))))&lt;br /&gt;&lt;br /&gt;(define (divides? a b)&lt;br /&gt;   (= (remainder b a) 0))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This procedure makes use of the &lt;code&gt;square&lt;/code&gt; procedure that was defined earlier.  You'll need to include it if you want to run the code in an interpreter.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;smallest-divisor&lt;/code&gt; procedure finds the smallest integral divisor (greater than 1) of a given number n in a straightforward way, by testing to see if n is divisible by each integer from 2 to √n.  Since the number of steps is between 1 and √n, the order of growth of the algorithm is O(√n).&lt;br /&gt;&lt;br /&gt;We can find the solutions to the exercise by simply running the code in an interpreter.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (smallest-divisor 199)&lt;br /&gt;199&lt;br /&gt;&amp;gt; (smallest-divisor 1999)&lt;br /&gt;1999&lt;br /&gt;&amp;gt; (smallest-divisor 19999)&lt;br /&gt;7&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, the first two numbers are prime because they are their own smallest divisor, but  the third is divisible by 7.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8706828198767451043?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8706828198767451043/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8706828198767451043" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8706828198767451043?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8706828198767451043?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-121-smallest-divisor.html" title="SICP Exercise 1.21: Smallest Divisor" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0MASXk4fip7ImA9WxBXFU4.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8597290053001948664</id><published>2010-01-26T13:06:00.006-05:00</published><updated>2010-01-26T13:44:08.736-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-26T13:44:08.736-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.20: GCD</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.5"&gt;1.2.5  Greatest Common Divisors&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.20&lt;/span&gt; asks us to consider the following iterative procedure that uses &lt;a href="http://en.wikipedia.org/wiki/Euclidean_algorithm"&gt;Euclid's Algorithm&lt;/a&gt; to comput the &lt;a href="http://en.wikipedia.org/wiki/Greatest_common_divisor"&gt;GCD&lt;/a&gt;:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (gcd a b)&lt;br /&gt;   (if (= b 0)&lt;br /&gt;       a&lt;br /&gt;       (gcd b (remainder a b))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're asked to illustrate the process generated by this procedure when using normal-order and applicative-order evaluation rules to evaluate &lt;code&gt;(gcd 206 40)&lt;/code&gt;.  How many &lt;code&gt;remainder&lt;/code&gt; operations are actually performed using each evaluation model?&lt;br /&gt;&lt;br /&gt;We learned the rules for both applicative-order and normal-order evaluation back in SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.5"&gt;1.1.5 The Substitution Model for Procedure Application&lt;/a&gt;.  We learned that under normal-order evaluation rules, the interpreter fully expands a procedure before reducing it.  Operand expressions are substituted for parameters until an expression involving only primitive operators is reached.  Under applicative-order rules, arguments are evaluated before operators are applied.  This can often avoid multiple unnecessary evaluations of the same expression, which is one of the reasons why Lisp uses applicative-order evaluation.&lt;br /&gt;&lt;br /&gt;In section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.6"&gt;1.1.6 Conditional Expressions and Predicates&lt;/a&gt; (see exercise 1.5) we're told to assume that the evaluation rule for the special form &lt;code&gt;if&lt;/code&gt; is the same whether we use normal or applicative order evaluation.  "The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression."  We'll continue using this assumption until we're told otherwise.&lt;br /&gt;&lt;br /&gt;Now let's put all of this together to illustrate both processes for &lt;code&gt;(gcd 206 40)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Normal-order evaluation&lt;/span&gt; - fully expand and then reduce.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(gcd 206 40)&lt;br /&gt;&lt;br /&gt;(if (= 40 0)&lt;br /&gt;    206&lt;br /&gt;    (gcd 40 (remainder 206 40)))&lt;br /&gt;&lt;br /&gt;(gcd 40 (remainder 206 40))&lt;br /&gt;&lt;br /&gt;(if (= (remainder 206 40) 0)&lt;br /&gt;    40&lt;br /&gt;    (gcd (remainder 206 40) (remainder 40 (remainder 206 40))))&lt;br /&gt;&lt;br /&gt;(if (= 6 0) ;; 1 remainder evaluated&lt;br /&gt;    40&lt;br /&gt;    (gcd (remainder 206 40) (remainder 40 (remainder 206 40))))&lt;br /&gt;&lt;br /&gt;(gcd (remainder 206 40) (remainder 40 (remainder 206 40)))&lt;br /&gt;&lt;br /&gt;(if (= (remainder 40 (remainder 206 40)) 0)&lt;br /&gt;    (remainder 206 40)&lt;br /&gt;    (gcd (remainder 40 (remainder 206 40))&lt;br /&gt;         (remainder (remainder 206 40)&lt;br /&gt;                    (remainder 40 (remainder 206 40)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;At this point both of the nested &lt;code&gt;remainder&lt;/code&gt; operations that were substituted in for &lt;code&gt;b&lt;/code&gt; in the &lt;code&gt;(= b 0)&lt;/code&gt; procedure need to be evaluated.  I'll combine these and show them as one step.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(if (= 4 0) ;; 2 remainders evaluated&lt;br /&gt;    (remainder 206 40)&lt;br /&gt;    (gcd (remainder 40 (remainder 206 40))&lt;br /&gt;         (remainder (remainder 206 40)&lt;br /&gt;                    (remainder 40 (remainder 206 40)))))&lt;br /&gt;&lt;br /&gt;(gcd (remainder 40 (remainder 206 40))&lt;br /&gt;     (remainder (remainder 206 40)&lt;br /&gt;                (remainder 40 (remainder 206 40))))&lt;br /&gt;&lt;br /&gt;(if (= (remainder (remainder 206 40)&lt;br /&gt;                  (remainder 40 (remainder 206 40)))&lt;br /&gt;       0)&lt;br /&gt;       (remainder 40 (remainder 206 40))&lt;br /&gt;       (gcd (remainder (remainder 206 40)&lt;br /&gt;                       (remainder 40 (remainder 206 40)))&lt;br /&gt;            (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                       (remainder (remainder 206 40)&lt;br /&gt;                                  (remainder 40 (remainder 206 40))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here again, multiple nested &lt;code&gt;remainder&lt;/code&gt; operations that were substituted in for &lt;code&gt;b&lt;/code&gt; in the &lt;code&gt;(= b 0)&lt;/code&gt; procedure need to be evaluated.  I'll combine all four and show them as one step.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(if (= 2 0) ;; 4 remainders evaluated&lt;br /&gt;    (remainder 40 (remainder 206 40))&lt;br /&gt;    (gcd (remainder (remainder 206 40)&lt;br /&gt;                    (remainder 40 (remainder 206 40)))&lt;br /&gt;         (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                    (remainder (remainder 206 40)&lt;br /&gt;                               (remainder 40 (remainder 206 40))))))&lt;br /&gt;&lt;br /&gt;(gcd (remainder (remainder 206 40)&lt;br /&gt;                (remainder 40 (remainder 206 40)))&lt;br /&gt;     (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                (remainder (remainder 206 40)&lt;br /&gt;                           (remainder 40 (remainder 206 40)))))&lt;br /&gt;&lt;br /&gt;(if (= (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                  (remainder (remainder 206 40)&lt;br /&gt;                             (remainder 40 (remainder 206 40)))) 0)&lt;br /&gt;    (remainder (remainder 206 40)&lt;br /&gt;               (remainder 40 (remainder 206 40)))&lt;br /&gt;    (gcd (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                    (remainder (remainder 206 40)&lt;br /&gt;                               (remainder 40 (remainder 206 40))))&lt;br /&gt;         (remainder (remainder (remainder 206 40)&lt;br /&gt;                               (remainder 40 (remainder 206 40)))&lt;br /&gt;                    (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                               (remainder (remainder 206 40)&lt;br /&gt;                                          (remainder 40&lt;br /&gt;                                                     (remainder 206 40)))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;There are seven nested &lt;code&gt;remainder&lt;/code&gt; operations to evaluate at this point.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(if (= 0 0) ;; 7 remainders evaluated&lt;br /&gt;    (remainder (remainder 206 40)&lt;br /&gt;               (remainder 40 (remainder 206 40)))&lt;br /&gt;    (gcd (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                    (remainder (remainder 206 40)&lt;br /&gt;                               (remainder 40 (remainder 206 40))))&lt;br /&gt;         (remainder (remainder (remainder 206 40)&lt;br /&gt;                               (remainder 40 (remainder 206 40)))&lt;br /&gt;                    (remainder (remainder 40 (remainder 206 40))&lt;br /&gt;                               (remainder (remainder 206 40)&lt;br /&gt;                                          (remainder 40&lt;br /&gt;                                                     (remainder 206&lt;br /&gt;                                                                40)))))))&lt;br /&gt;&lt;br /&gt;(remainder (remainder 206 40)&lt;br /&gt;           (remainder 40 (remainder 206 40)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Finally, we can evaluate these four &lt;code&gt;remainder&lt;/code&gt; operations to come up with the answer (GCD) and the total.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;2 ;; 18 total remainders evaluated&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Applicative-order evaluation&lt;/span&gt; - evaluate arguments and then apply operands.  This one is a little bit easier to follow.  With each substitution, we just evaluate the operands that we need before applying the operators at each step.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(gcd 206 40)&lt;br /&gt;&lt;br /&gt;(if (= 40 0)&lt;br /&gt;    206&lt;br /&gt;    (gcd 40 (remainder 206 40))))&lt;br /&gt;&lt;br /&gt;(gcd 40 (remainder 206 40))&lt;br /&gt;&lt;br /&gt;(gcd 40 6) ;; 1st remainder evaluated&lt;br /&gt;&lt;br /&gt;(if (= 6 0)&lt;br /&gt;    40&lt;br /&gt;    (gcd 6 (remainder 40 6)))&lt;br /&gt;&lt;br /&gt;(gcd 6 (remainder 40 6))&lt;br /&gt;&lt;br /&gt;(gcd 6 4) ;; 2nd remainder evaluated&lt;br /&gt;&lt;br /&gt;(if (= 4 0)&lt;br /&gt;    6&lt;br /&gt;    (gcd 4 (remainder 6 4)))&lt;br /&gt;&lt;br /&gt;(gcd 4 (remainder 6 4))&lt;br /&gt;&lt;br /&gt;(gcd 4 2) ;; 3rd remainder evaluated&lt;br /&gt;&lt;br /&gt;(if (= 2 0)&lt;br /&gt;    4&lt;br /&gt;    (gcd 2 (remainder 4 2)))&lt;br /&gt;&lt;br /&gt;(gcd 2 (remainder 4 2))&lt;br /&gt;&lt;br /&gt;(gcd 2 0) ;; 4th remainder evaluated&lt;br /&gt;&lt;br /&gt;(if (= 0 0)&lt;br /&gt;    2&lt;br /&gt;    (gcd 0 (remainder 2 0)))&lt;br /&gt;&lt;br /&gt;2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, using applicative-order evaluation, &lt;code&gt;remainder&lt;/code&gt; was only evaluated four times, compared to 18 times using normal-order evaluation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8597290053001948664?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8597290053001948664/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8597290053001948664" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8597290053001948664?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8597290053001948664?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-120-gcd.html" title="SICP Exercise 1.20: GCD" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;AkEDRngyeCp7ImA9WxBXGE0.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3093692380116308350</id><published>2010-01-23T11:10:00.005-05:00</published><updated>2010-01-29T18:44:37.690-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-29T18:44:37.690-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="perfect numbers" /><category scheme="http://www.blogger.com/atom/ns#" term="unsolved" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>Unsolved: Odd Perfect Numbers</title><content type="html">A perfect number is a number that is the sum of its proper divisors (i.e., including 1 but excluding itself).&lt;br /&gt;&lt;br /&gt;For example, the smallest perfect number is 6.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;1 + 2 + 3 = &lt;span style="font-weight: bold;"&gt;6&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The next two perfect numbers are&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;1 + 2 + 4 + 7 + 14 = &lt;span style="font-weight: bold;"&gt;28&lt;/span&gt;&lt;br /&gt;1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 = &lt;span style="font-weight: bold;"&gt;496&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;See sequence &lt;a href="http://www.research.att.com/%7Enjas/sequences/table?a=396&amp;amp;fmt=4"&gt;A000396&lt;/a&gt; in &lt;a href="http://www.research.att.com/%7Enjas/sequences/"&gt;OEIS&lt;/a&gt; for a list of the first ten perfect numbers.&lt;br /&gt;&lt;br /&gt;On a related note, a number that is smaller than the sum of its proper divisors is an &lt;a href="http://mathworld.wolfram.com/AbundantNumber.html"&gt;abundant&lt;/a&gt; number, while a number greater than the sum of its proper divisors is called &lt;a href="http://mathworld.wolfram.com/DeficientNumber.html"&gt;deficient&lt;/a&gt;.  The smallest abundant number is 12, whose proper divisors sum to 16.&lt;br /&gt;&lt;br /&gt;All of the perfect numbers that have been discovered so far are even.&lt;br /&gt;&lt;br /&gt;&lt;div style="border: 1px solid rgb(153, 153, 153); padding: 15px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); width: 90%;"&gt;The problem is to find an odd perfect number, or prove that no odd perfect numbers exist.&lt;/div&gt;&lt;br /&gt;If there is an odd perfect number, &lt;a href="http://en.wikipedia.org/wiki/Perfect_number#Odd_perfect_numbers"&gt;we already know a lot about it&lt;/a&gt;.  It must be at least 300 digits long, with at least 75 prime factors, at least 9 of them distinct.  Its largest prime factor must be greater than 100,000,000.  Its second largest prime factor is greater than 10,000, and its third largest is greater than 100.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-3093692380116308350?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3093692380116308350/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3093692380116308350" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3093692380116308350?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3093692380116308350?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/unsolved-odd-perfect-numbers.html" title="Unsolved: Odd Perfect Numbers" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;DkUDQng-eip7ImA9WxBXEUQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8529960300376325759</id><published>2010-01-22T15:43:00.004-05:00</published><updated>2010-01-22T16:04:33.652-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-22T16:04:33.652-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.19: Computing Fibonacci numbers</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4"&gt;1.2.4  Exponentiation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.19&lt;/span&gt; asks us to complete a procedure for computing Fibonacci numbers in a logarithmic number of steps.  The following code is given:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fib n)&lt;br /&gt;   (fib-iter 1 0 0 1 n))&lt;br /&gt;&lt;br /&gt;(define (fib-iter a b p q count)&lt;br /&gt;   (cond ((= count 0) b)&lt;br /&gt;         ((even? count)&lt;br /&gt;          (fib-iter a&lt;br /&gt;                    b&lt;br /&gt;                    &amp;lt;??&amp;gt;      ; compute p'&lt;br /&gt;                    &amp;lt;??&amp;gt;      ; compute q'&lt;br /&gt;                    (/ count 2)))&lt;br /&gt;         (else (fib-iter (+ (* b q) (* a q) (* a p))&lt;br /&gt;                         (+ (* b p) (* a q))&lt;br /&gt;                         p&lt;br /&gt;                         q&lt;br /&gt;                         (- count 1)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're reminded of the transformation of the state variables a and b in the original fib-iter procedure from section 1.2.2: a ← a + b and b ← a.  If these state changes are labeled transformation T, then applying T repeatedly for n iterations starting with a = 1 and b = 0 produces the pair a = Fib(n + 1) and b = Fib(n).  So the Fibonacci numbers are produced by the nth power of the transformation T, or T&lt;sup&gt;n&lt;/sup&gt;, starting with the pair (1, 0).&lt;br /&gt;&lt;br /&gt;We are then asked to consider the family of transformations T&lt;sub&gt;pq&lt;/sub&gt; which transforms the pair (a, b) according to the following rules:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a ← bq + aq + ap&lt;br /&gt;b ← bp + aq&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We can verify by quick substitution that the original transformation T is just a special case of T&lt;sub&gt;pq&lt;/sub&gt;, where p = 0 and q = 1.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a ← b(1) + a(1) + a(0)&lt;br /&gt;a ← b + a&lt;br /&gt;&lt;br /&gt;b ← b(0) + a(1)&lt;br /&gt;b ← a&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We are asked to show that if we apply T&lt;sub&gt;pq&lt;/sub&gt; twice, the effect is the same as using a single transformation T&lt;sub&gt;p'q'&lt;/sub&gt; of the same form, and compute p' and q' in terms of p and q.  This will give us an explicit way to square these transformations, which we can use to compute T&lt;sup&gt;n&lt;/sup&gt; using successive squaring, just like the fast-expt procedure from exercise &lt;a href="http://www.billthelizard.com/2010/01/sicp-exercise-116-fast-exponentiation.html"&gt;1.16&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We can apply T&lt;sub&gt;pq&lt;/sub&gt; twice by defining new variables and using substitution.  Let's define a&lt;sub&gt;1&lt;/sub&gt; and b&lt;sub&gt;1&lt;/sub&gt; as the results of applying transformation T&lt;sub&gt;pq&lt;/sub&gt; once&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sub&gt;1&lt;/sub&gt; = bq + aq + ap&lt;br /&gt;b&lt;sub&gt;1&lt;/sub&gt; = bp + aq&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The next step is to define a&lt;sub&gt;2&lt;/sub&gt; and b&lt;sub&gt;2&lt;/sub&gt; and apply the tranformation a second time, this time using a&lt;sub&gt;1&lt;/sub&gt; and b&lt;sub&gt;1&lt;/sub&gt; in place of a and b.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sub&gt;2&lt;/sub&gt; = b&lt;sub&gt;1&lt;/sub&gt;q + a&lt;sub&gt;1&lt;/sub&gt;q + a&lt;sub&gt;1&lt;/sub&gt;p&lt;br /&gt;b&lt;sub&gt;2&lt;/sub&gt; = b&lt;sub&gt;1&lt;/sub&gt;p + a&lt;sub&gt;1&lt;/sub&gt;q&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now that we have a system of equations defined, we can use substitution on our way to simplifying.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sub&gt;2&lt;/sub&gt; = (bp + aq)q + (bq + aq + ap)q + (bq + aq + ap)p&lt;br /&gt;b&lt;sub&gt;2&lt;/sub&gt; = (bp + aq)p + (bq + aq + ap)q&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The second equation is shorter, so it should be easier to manipulate.  Remember, we're trying to find p' and q', so we need to rewrite the equation to fit the form&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;b&lt;sub&gt;2&lt;/sub&gt; = bp' + aq'&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;where p' and q' can be computed in terms of q and p.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;b&lt;sub&gt;2&lt;/sub&gt; = (bp + aq)p + (bq + aq + ap)q&lt;br /&gt;= (bpp + apq) + (bqq + aqq + apq)&lt;br /&gt;= bpp + apq + bqq + aqq + apq&lt;br /&gt;= (bpp + bqq) + (2apq + aqq)&lt;br /&gt;= b(pp + qq) + a(2qp + qq)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;From this we can see that p' and q' can be computed using the following equations:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;p' = p&lt;sup&gt;2&lt;/sup&gt; + q&lt;sup&gt;2&lt;/sup&gt;&lt;br /&gt;q' = 2pq + q&lt;sup&gt;2&lt;/sup&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Manipulating the equation for a&lt;sub&gt;2&lt;/sub&gt; in the same way, we can verify those results.  This time we're trying to fit the form&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sub&gt;2&lt;/sub&gt; = bq' + aq' + ap'&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The groupings required for this manipulation are made even easier by the fact that we now already know the formulas for p' and q'.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;a&lt;sub&gt;2&lt;/sub&gt; = (bp + aq)q + (bq + aq + ap)q + (bq + aq + ap)p&lt;br /&gt;= (bpq + aqq) + (bqq + aqq + apq) + (bpq + apq + app)&lt;br /&gt;= bpq + aqq + bqq + aqq + apq + bpq + apq + app&lt;br /&gt;= (bpq + bpq + bqq) + (apq + apq + aqq) + (app + aqq)&lt;br /&gt;= b(pq + pq + qq) + a(pq + pq + qq) + a(pp + qq)&lt;br /&gt;= b(2pq + qq) + a(2pq + qq) + a(pp + qq)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now that we've verified the formulas for p' and q' in terms of p and q, we can use them to complete the procedure we were given.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fib n)&lt;br /&gt;   (fib-iter 1 0 0 1 n))&lt;br /&gt;&lt;br /&gt;(define (fib-iter a b p q count)&lt;br /&gt;   (cond ((= count 0) b)&lt;br /&gt;         ((even? count)&lt;br /&gt;          (fib-iter a&lt;br /&gt;                    b&lt;br /&gt;                    (+ (* p p) (* q q))     ; compute p'&lt;br /&gt;                    (+ (* 2 p q) (* q q))   ; compute q'&lt;br /&gt;                    (/ count 2)))&lt;br /&gt;         (else (fib-iter (+ (* b q) (* a q) (* a p))&lt;br /&gt;                         (+ (* b p) (* a q))&lt;br /&gt;                         p&lt;br /&gt;                         q&lt;br /&gt;                         (- count 1)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can test several known values in an interpreter to verify that this actually works.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (fib 0)&lt;br /&gt;0&lt;br /&gt;&amp;gt; (fib 1)&lt;br /&gt;1&lt;br /&gt;&amp;gt; (fib 2)&lt;br /&gt;1&lt;br /&gt;&amp;gt; (fib 3)&lt;br /&gt;2&lt;br /&gt;&amp;gt; (fib 5)&lt;br /&gt;5&lt;br /&gt;&amp;gt; (fib 10)&lt;br /&gt;55&lt;br /&gt;&amp;gt; (fib 20)&lt;br /&gt;6765&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8529960300376325759?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8529960300376325759/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8529960300376325759" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8529960300376325759?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8529960300376325759?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-119-computing-fibonacci.html" title="SICP Exercise 1.19: Computing Fibonacci numbers" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DUEFQH07cSp7ImA9WxBQFEQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-7079560428571431597</id><published>2010-01-14T14:26:00.003-05:00</published><updated>2010-01-14T14:33:31.309-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-14T14:33:31.309-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.18: Iterative multiplication</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4"&gt;1.2.4  Exponentiation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.18&lt;/span&gt; asks us to use the results from the two previous exercises (&lt;a href="http://www.billthelizard.com/2010/01/sicp-exercise-116-fast-exponentiation.html"&gt;1.16&lt;/a&gt; and &lt;a href="http://www.billthelizard.com/2010/01/sicp-exercise-117-multiplication-by.html"&gt;1.17&lt;/a&gt;) to devise a procedure that generates an iterative process for multiplying two integers in terms of adding, doubling and halving, and which uses a logarithmic number of steps.&lt;br /&gt;&lt;br /&gt;The key idea from exercise 1.16 was to keep an additional state variable &lt;code&gt;a&lt;/code&gt;, and manipulate the state transition so that the product (a * b&lt;sup&gt;n&lt;/sup&gt;) remained unchanged.  We can modify our solution to exercise 1.17 to use the same idea.  Since we're now dealing with multiplication instead of exponentiation, the invariant quantity will be (a * b + p) where &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are the two operands, and &lt;code&gt;p&lt;/code&gt; will be our state variable.  Initially &lt;code&gt;p&lt;/code&gt; will be 0, but by the end of the iterative process it will hold the product (a * b).&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;br /&gt;(define (double x)&lt;br /&gt;   (+ x x))&lt;br /&gt;&lt;br /&gt;(define (halve x)&lt;br /&gt;   (/ x 2))&lt;br /&gt;&lt;br /&gt;(define (mult-iter a b p)&lt;br /&gt;   (cond ((= 0 b) p)&lt;br /&gt;         ((even? b) (mult-iter (double a) (halve b) p))&lt;br /&gt;         (else (mult-iter a (- b 1) (+ a p)))))&lt;br /&gt;&lt;br /&gt;(define (mult a b)&lt;br /&gt;   (mult-iter a b 0))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-7079560428571431597?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/7079560428571431597/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=7079560428571431597" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7079560428571431597?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7079560428571431597?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-118-iterative.html" title="SICP Exercise 1.18: Iterative multiplication" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEUESH4-cCp7ImA9WxBQFEw.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-6997241069329976275</id><published>2010-01-13T14:36:00.005-05:00</published><updated>2010-01-13T14:50:09.058-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-13T14:50:09.058-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.17: Multiplication by repeated addition</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4"&gt;1.2.4  Exponentiation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.17&lt;/span&gt; asks us to design a multiplication procedure analogous to &lt;code&gt;fast-expt&lt;/code&gt; that uses a logarithmic number of steps.  We're told that in addition to adding, we can use procedures for doubling or halving an integer argument.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (double x)&lt;br /&gt;   (+ x x))&lt;br /&gt;&lt;br /&gt;(define (halve x)&lt;br /&gt;   (/ x 2))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We'll also use the same &lt;code&gt;even?&lt;/code&gt; procedure we've seen before:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The following multiplication procedure that takes a linear number of steps is given:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (* a b)&lt;br /&gt;   (if (= b 0)&lt;br /&gt;       0&lt;br /&gt;       (+ a (* a (- b 1)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This procedure defines multiplication in terms of the algorithm we all learned in grade school: add a to itself b times.&lt;br /&gt;&lt;br /&gt;The exercise also makes reference to the following &lt;code&gt;fast-expt&lt;/code&gt; procedure, which we can use as a guide:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fast-expt b n)&lt;br /&gt;   (cond ((= n 0) 1)&lt;br /&gt;         ((even? n) (square (fast-expt b (/ n 2))))&lt;br /&gt;         (else (* b (fast-expt b (- n 1))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This procedure makes use of the following observations:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;b&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;n&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt; = (b&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;n/2&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt;)&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;2&lt;/sup&gt; if n is even&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;b&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;n&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt; = b * b&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;n-1&lt;/sup&gt; if n is odd&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We can define similar rules for integer multiplication.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;a * b = 2 * (a * b/2)&lt;/span&gt; if be is even&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;a * b = a + a * (b - 1)&lt;/span&gt; if b is odd&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The first rule tells us when to use our procedures &lt;code&gt;double&lt;/code&gt; and &lt;code&gt;halve&lt;/code&gt;.  The second rule just lets us take an odd b and make it even in preparation for the next iteration.  Translating these rule into a Scheme procedure give us:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fast-mult a b)&lt;br /&gt;   (cond ((= b 0) 0)&lt;br /&gt;         ((= b 1) a)&lt;br /&gt;         ((even? b) (double (fast-mult a (halve b))))&lt;br /&gt;         (else (+ a (fast-mult a (- b 1))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The procedure takes a logarithmic number of steps.  If you double the size of the input parameter b, the procedure takes only one more step to compute the product.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-6997241069329976275?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/6997241069329976275/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=6997241069329976275" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6997241069329976275?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6997241069329976275?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-117-multiplication-by.html" title="SICP Exercise 1.17: Multiplication by repeated addition" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;AkIGQXg5fSp7ImA9WxBQE0g.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-228954992735399747</id><published>2010-01-12T08:26:00.003-05:00</published><updated>2010-01-12T23:55:20.625-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-12T23:55:20.625-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzles" /><category scheme="http://www.blogger.com/atom/ns#" term="exercises" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="practice" /><title>Guest article on Programming Praxis</title><content type="html">I was excited to be asked to be the guest author for an article on one of my favorite programming blogs, &lt;a href="http://programmingpraxis.com/"&gt;Programming Praxis&lt;/a&gt;.  If you're not familiar with the site, Programming Praxis provides weekly practice exercieses to "sharpen your saw" on.  It was inspired in part by &lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt;, but the problems on Programming Praxis focus more on developing programming skills and usually require less advanced math than those on Project Euler.&lt;br /&gt;&lt;br /&gt;To follow up earlier exercises on &lt;a href="http://programmingpraxis.com/2009/10/09/calculating-pi/"&gt;Calculating Pi&lt;/a&gt; and &lt;a href="http://programmingpraxis.com/2009/12/18/calculating-logarithms/"&gt;Logarithms&lt;/a&gt;, my article is on &lt;a href="http://programmingpraxis.com/2010/01/12/calculating-sines/"&gt;Calculating Sines&lt;/a&gt; using two different methods, the Taylor series and the Triple-angle formula.  The sample solutions are written in Scheme, but readers are encouraged to submit solutions in any language they choose  (see the &lt;a href="http://programmingpraxis.com/contents/howto-posting-source-code/"&gt;HOWTO on posting source code&lt;/a&gt; to post your own solution).  Since I'm still a relative newbie to Scheme (I'm currently &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;still in chapter one of SICP&lt;/a&gt;), I'll be interested to see what alternate solutions you can come up with.&lt;br /&gt;&lt;br /&gt;The article is also currently featured on &lt;a href="http://www.scheme.dk/planet/"&gt;Planet Scheme&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-228954992735399747?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/228954992735399747/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=228954992735399747" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/228954992735399747?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/228954992735399747?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/guest-article-on-programming-praxis.html" title="Guest article on Programming Praxis" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEQHQHczfyp7ImA9WxBQFEw.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8328830979852332708</id><published>2010-01-11T16:07:00.007-05:00</published><updated>2010-01-13T14:52:11.987-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-13T14:52:11.987-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.16: Fast Exponentiation</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4"&gt;1.2.4  Exponentiation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.16&lt;/span&gt; asks us to design an exponentiation procedure that evolves an iterative process using successive squaring and uses a logarithmic number of steps.  A hint tells us to use the observation that (b&lt;sup&gt;n/2&lt;/sup&gt;)&lt;sup&gt;2&lt;/sup&gt; = (b&lt;sup&gt;2&lt;/sup&gt;)&lt;sup&gt;n/2&lt;/sup&gt; and to keep, along with the exponent &lt;code&gt;n&lt;/code&gt; and base &lt;code&gt;b&lt;/code&gt;, an additional state variable &lt;code&gt;a&lt;/code&gt;, and to define the state transformation in such a way that the product &lt;code&gt;a * b&lt;sup&gt;n&lt;/sup&gt;&lt;/code&gt; is unchanged from state to state.  The value of &lt;code&gt;a&lt;/code&gt; should start at 1, and should contain the final answer by the end of the process.&lt;br /&gt;&lt;br /&gt;Earlier in section 1.2.4, we were given the procedure:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (even? n)&lt;br /&gt;   (= (remainder n 2) 0))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;which tests whether an integer is even.  This will come in handy again for this exercise, since we'll need to adjust &lt;code&gt;a&lt;/code&gt; by a different amount when &lt;code&gt;n&lt;/code&gt; is even than when &lt;code&gt;n&lt;/code&gt; is odd.&lt;br /&gt;&lt;br /&gt;We'll also use the following simple procedure for squaring a number:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;With those building blocks in place, we can define our iterative procedure.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (expt-iter b n a)&lt;br /&gt;   (cond ((= n 0) a)&lt;br /&gt;         ((even? n) (expt-iter (square b) (/ n 2) a))&lt;br /&gt;         (else (expt-iter  b (- n 1) (* a b)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We call the procedure &lt;code&gt;expt-iter&lt;/code&gt; with the arguments base &lt;code&gt;b&lt;/code&gt;, exponent &lt;code&gt;n&lt;/code&gt;, and the state variable &lt;code&gt;a&lt;/code&gt;.  The first thing we do is check to see if the exponent is 0.  If so, we've reached the end of the procedure and just return the value of &lt;code&gt;a&lt;/code&gt;.  Next we check to see if &lt;code&gt;n&lt;/code&gt; is even.  If it is, we use the observation that (b&lt;sup&gt;n/2&lt;/sup&gt;)&lt;sup&gt;2&lt;/sup&gt; = (b&lt;sup&gt;2&lt;/sup&gt;)&lt;sup&gt;n/2&lt;/sup&gt; to transform state information by squaring &lt;code&gt;b&lt;/code&gt; and dividing &lt;code&gt;n&lt;/code&gt; by 2.  Finally, if &lt;code&gt;n&lt;/code&gt; is odd we transform state information by reducing &lt;code&gt;n&lt;/code&gt; by 1 and multiplying &lt;code&gt;a&lt;/code&gt; by the base &lt;code&gt;b&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The only thing that's left to do is define a procedure that calls &lt;code&gt;expt-iter&lt;/code&gt; with the correct initial values.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (fast-expt b n)&lt;br /&gt;   (expt-iter b n 1))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here are a few sample runs of the procedure:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (fast-expt 2 2)&lt;br /&gt;4&lt;br /&gt;&amp;gt; (fast-expt 2 3)&lt;br /&gt;8&lt;br /&gt;&amp;gt; (fast-expt 2 10)&lt;br /&gt;1024&lt;br /&gt;&amp;gt; (fast-expt 3 3)&lt;br /&gt;27&lt;br /&gt;&amp;gt; (fast-expt 5 5)&lt;br /&gt;3125&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can try running the procedure with large values of &lt;code&gt;n&lt;/code&gt; to verify that it really is fast.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8328830979852332708?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8328830979852332708/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8328830979852332708" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8328830979852332708?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8328830979852332708?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/sicp-exercise-116-fast-exponentiation.html" title="SICP Exercise 1.16: Fast Exponentiation" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;C0MBQHk5fyp7ImA9WxBQEU4.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-6755815435404710332</id><published>2010-01-10T08:39:00.006-05:00</published><updated>2010-01-10T08:50:51.727-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-10T08:50:51.727-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="algebra" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>Math visualization: Multiplying Two Binomials</title><content type="html">In my earlier post &lt;a href="http://www.billthelizard.com/2009/12/math-visualization-x-1-2.html"&gt;Math visualization: (x + 1)&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;, I showed how to draw a picture that proved the equality&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;(x + 1)&lt;sup&gt;2&lt;/sup&gt; = x&lt;sup&gt;2&lt;/sup&gt; + 2x + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;An alert reader commented that (x + 1)&lt;sup&gt;2&lt;/sup&gt; is a specific instance of the binomial squared&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;(x + a)&lt;sup&gt;2&lt;/sup&gt; = x&lt;sup&gt;2&lt;/sup&gt; + 2ax + a&lt;sup&gt;2&lt;/sup&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Here's a visualization of that equality:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PnLYRqe0k9g/S0nZrwyLyCI/AAAAAAAAAQ8/PUoKC5qRbR8/s1600-h/binomial-squared.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 307px;" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/S0nZrwyLyCI/AAAAAAAAAQ8/PUoKC5qRbR8/s320/binomial-squared.png" alt="" id="BLOGGER_PHOTO_ID_5425106571997464610" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It turns out that the illustration can be generalized a little bit further to cover multiplying two binomials that form a rectangle (not just a perfect square).&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;(x + a)(x + b) = x&lt;sup&gt;2&lt;/sup&gt; + ax + bx + ab&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PnLYRqe0k9g/S0nZ-dZsl9I/AAAAAAAAARE/MtAEo96oqp0/s1600-h/multiply-two-binomials.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 284px;" src="http://1.bp.blogspot.com/_PnLYRqe0k9g/S0nZ-dZsl9I/AAAAAAAAARE/MtAEo96oqp0/s320/multiply-two-binomials.png" alt="" id="BLOGGER_PHOTO_ID_5425106893211998162" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you want to see how this idea can be extended into the third dimension, check out Montessori World's page on the &lt;a href="http://homepage.mac.com/montessoriworld/mwei/sensory/sbinoml.html"&gt;Binomial Cube&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-6755815435404710332?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/6755815435404710332/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=6755815435404710332" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6755815435404710332?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6755815435404710332?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/math-visualization-multiplying-two.html" title="Math visualization: Multiplying Two Binomials" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_PnLYRqe0k9g/S0nZrwyLyCI/AAAAAAAAAQ8/PUoKC5qRbR8/s72-c/binomial-squared.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0cBSXwycSp7ImA9WxBRFks.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3991930857010675638</id><published>2010-01-04T21:54:00.011-05:00</published><updated>2010-01-04T22:10:58.299-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-04T22:10:58.299-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="unsolved" /><category scheme="http://www.blogger.com/atom/ns#" term="primes" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>Unsolved: Twin Primes Conjecture</title><content type="html">Prime numbers, as most school children can tell you, are those numbers that are evenly divisible by only themselves and 1.  The first few primes are&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;2, 3, 5, 7, 11, 13, 17...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We've known that there are infinitely many primes since c. 300 BC when it was proven by &lt;a href="http://en.wikipedia.org/wiki/Euclid"&gt;Euclid of Alexandria&lt;/a&gt;.  Euclid used a very simple and elegant proof by contradiction.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Euclid's proof of the infinitude of primes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First, assume that there are a finite number of primes, p1, p2, p3, ..., pn.&lt;br /&gt;&lt;br /&gt;Now let&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;Q = (p1 * p2 * ... * pn) + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;That is, Q is equal to all of the primes multiplied together plus one.&lt;br /&gt;&lt;br /&gt;By the &lt;a href="http://mathworld.wolfram.com/FundamentalTheoremofArithmetic.html"&gt;Fundamental Theorem of Arithmetic&lt;/a&gt;, Q is either prime or it can be written as the product of two or more primes.  However, none of the primes in our list evenly divides Q.  If any prime in our list did evenly divide Q, then that same prime would also evenly divide 1, since&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;Q - (p1 * p2 * ... * pn) = 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This contradicts the assumption that we had listed all the primes.  So no matter how many primes we start with in our list, there must always be more primes.  (Note that this proof does not claim that Q itself is prime, just that there must be some prime not in the initial list.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Twin primes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Twin primes are those pairs of numers that have a difference of two, and that are both prime.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;3, 5&lt;br /&gt;5, 7&lt;br /&gt;11, 13&lt;br /&gt;17, 19&lt;br /&gt;...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="border: 1px solid rgb(153, 153, 153); padding: 15px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); width: 90%;"&gt;&lt;span style="font-weight: bold;"&gt;The Twin prime conjecture&lt;/span&gt;, which dates back to the 18th century, simply states that there are infinitely many twin primes.&lt;/div&gt;&lt;br /&gt;Given the simplicity of Euclid's proof of the infinitude of primes, it's tempting to hope for an equally simple proof to the Twin prime conjecture.  Needless to say, such a proof has not been found.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other facts about twin primes:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Other than (3, 5), all twin primes have the form (6n - 1, 6n + 1).&lt;br /&gt;&lt;br /&gt;In 1919 &lt;a href="http://en.wikipedia.org/wiki/Viggo_Brun"&gt;Viggo Brun&lt;/a&gt; showed that the sum of the reciprocals of the twin primes converges to a definite number, now known as Brun's constant (approximately 1.902160578).&lt;br /&gt;&lt;br /&gt;In 1994, while in the process of estimating Brun's constant by calculating the twin primes up to 10&lt;sup&gt;14&lt;/sup&gt;, Thomas Nicely discovered the infamous &lt;a href="http://en.wikipedia.org/wiki/Pentium_FDIV_bug"&gt;Pentium bug&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://primes.utm.edu/primes/page.php?id=89650"&gt;largest known twin primes&lt;/a&gt; (as of January 2010) are a pair of 100,355 digit primes with the values 65516468355 * 2&lt;sup&gt;333333&lt;/sup&gt; ± 1.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-3991930857010675638?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3991930857010675638/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3991930857010675638" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3991930857010675638?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3991930857010675638?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2010/01/unsolved-twin-primes-conjecture.html" title="Unsolved: Twin Primes Conjecture" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DkIARXo_eip7ImA9WxBQEk8.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8982255178166287565</id><published>2009-12-26T23:27:00.007-05:00</published><updated>2010-01-11T10:42:24.442-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T10:42:24.442-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="algebra" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>Math visualization: (x + 1)2</title><content type="html">You may remember this from high-school algebra (or perhaps earlier for some).  Expand (x + 1)&lt;sup&gt;2&lt;/sup&gt; using the &lt;a href="http://en.wikipedia.org/wiki/FOIL_method"&gt;FOIL&lt;/a&gt; method.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;(x + 1)&lt;sup&gt;2&lt;/sup&gt; = (x + 1)(x + 1)&lt;br /&gt;= x&lt;sup&gt;2&lt;/sup&gt; + x + x + 1&lt;br /&gt;= x&lt;sup&gt;2&lt;/sup&gt; + 2x + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;A neat way to visualize this equality, and hopefully help remember the factorization of the resulting polynomial, is to look at how the pieces fit together.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PnLYRqe0k9g/Szbl1QpiiuI/AAAAAAAAAQ0/sO7B9goT3-0/s1600-h/x-squared-plus-1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 241px;" src="http://4.bp.blogspot.com/_PnLYRqe0k9g/Szbl1QpiiuI/AAAAAAAAAQ0/sO7B9goT3-0/s320/x-squared-plus-1.png" alt="" id="BLOGGER_PHOTO_ID_5419771904751995618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;When they're arranged in this way, it's easy to see that the pieces squeeze together to form a larger square that has a length of (x + 1) on a side, proving the equality.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related posts&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.billthelizard.com/2009/07/six-visual-proofs_25.html"&gt;Six Visual Proofs&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.billthelizard.com/2010/01/math-visualization-multiplying-two.html"&gt;Multiplying Two Binomials&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-8982255178166287565?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8982255178166287565/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8982255178166287565" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8982255178166287565?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8982255178166287565?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2009/12/math-visualization-x-1-2.html" title="Math visualization: (x + 1)&lt;sup&gt;2&lt;/sup&gt;" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_PnLYRqe0k9g/Szbl1QpiiuI/AAAAAAAAAQ0/sO7B9goT3-0/s72-c/x-squared-plus-1.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">12</thr:total></entry><entry gd:etag="W/&quot;CkQBRno-eip7ImA9WxBQFUU.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-1144092031394324071</id><published>2009-12-24T23:00:00.007-05:00</published><updated>2010-01-15T13:32:37.452-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-15T13:32:37.452-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.15: Calculating sines</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.3"&gt;1.2.3  Orders of Growth&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.15&lt;/span&gt; shows an interesting procedure for computing the sine of an angle (in radians) by combined use of the approximation sin x ~ x (if x is sufficiently small) and the trigonometric identity&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;sin r = 3 * sin(r/3) - 4 * sin&lt;sup&gt;3&lt;/sup&gt;(r/3)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;which is used to reduce the argument of sin.  The code provided implements the computation:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (cube x) (* x x x))&lt;br /&gt;&lt;br /&gt;(define (p x) (- (* 3 x) (* 4 (cube x))))&lt;br /&gt;&lt;br /&gt;(define (sine angle)&lt;br /&gt;   (if (not (&amp;gt; (abs angle) 0.1))&lt;br /&gt;       angle&lt;br /&gt;       (p (sine (/ angle 3.0)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The exercise goes on to ask the following two questions:&lt;br /&gt;&lt;br /&gt;a.  How many times is the procedure &lt;code&gt;p&lt;/code&gt; applied when &lt;code&gt;(sine 12.15)&lt;/code&gt; is evaluated?&lt;br /&gt;&lt;br /&gt;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 &lt;code&gt;sine&lt;/code&gt; procedure when &lt;code&gt;(sine a)&lt;/code&gt; is evaluated?&lt;br /&gt;&lt;br /&gt;Looking at how the process executes will help us answer both questions.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(sine 12.15)&lt;br /&gt;(p (sine 4.05))&lt;br /&gt;(p (p (sine 1.35)))&lt;br /&gt;(p (p (p (sine 0.45))))&lt;br /&gt;(p (p (p (p (sine 0.15)))))&lt;br /&gt;(p (p (p (p (p (sine 0.05))))))&lt;br /&gt;(p (p (p (p (p 0.05)))))&lt;br /&gt;(p (p (p (p 0.1495))))&lt;br /&gt;(p (p (p 0.4351345505)))&lt;br /&gt;(p (p 0.9758465331678772))&lt;br /&gt;(p -0.7895631144708228)&lt;br /&gt;-0.39980345741334&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As long as the angle stays greater than 0.1, the process keeps recursing.  There are five calls to the procedure &lt;code&gt;p&lt;/code&gt; before that happens.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Complexity&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;sine&lt;/code&gt; procedure is recursive, but it makes only a single call to itself, so it isn't tree recursive and its complexity isn't nearly as bad as some of the procedures we've seen in previous exercises.  The complexity for this procedure in both space and number of steps is actually better than linear.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Space&lt;/span&gt; - The amount of space required by this procedure would increase linearly as the input size is tripled.  Only the calls to procedure &lt;code&gt;p&lt;/code&gt; are deferred, and we can triple the size of the input before an additional call would be made.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Number of steps&lt;/span&gt; - It's also easy to see that we can triple the value of the starting input angle and only one more step would be required by this procedure.&lt;br /&gt;&lt;br /&gt;The complexity of both the space and the number of steps required by this procedure can be described as &lt;span style="font-weight: bold;"&gt;O(log n)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-1144092031394324071?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/1144092031394324071/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=1144092031394324071" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1144092031394324071?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1144092031394324071?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2009/12/sicp-exercise-115-calculating-sines.html" title="SICP Exercise 1.15: Calculating sines" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CkQFQXw9eSp7ImA9WxBQFUU.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-5439647743608276098</id><published>2009-12-22T23:50:00.016-05:00</published><updated>2010-01-15T13:31:50.261-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-15T13:31:50.261-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sicp" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP Exercise 1.14: Counting change</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.3"&gt;1.2.3 Orders of Growth&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 1.14&lt;/span&gt; asks us to draw the tree illustrating the process generated by the &lt;code&gt;count-change&lt;/code&gt; procedure presented in &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2"&gt;section 1.2.2&lt;/a&gt; in making change for 11 cents.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;(define (count-change amount)&lt;br /&gt;   (cc amount 5))&lt;br /&gt;&lt;br /&gt;(define (cc amount kinds-of-coins)&lt;br /&gt;   (cond ((= amount 0) 1)&lt;br /&gt;         ((or (&amp;lt; amount 0) (= kinds-of-coins 0)) 0)&lt;br /&gt;         (else (+ (cc amount&lt;br /&gt;                      (- kinds-of-coins 1))&lt;br /&gt;                  (cc (- amount&lt;br /&gt;                         (first-denomination kinds-of-coins))&lt;br /&gt;                      kinds-of-coins)))))&lt;br /&gt;&lt;br /&gt;(define (first-denomination kinds-of-coins)&lt;br /&gt;   (cond ((= kinds-of-coins 1) 1)&lt;br /&gt;         ((= kinds-of-coins 2) 5)&lt;br /&gt;         ((= kinds-of-coins 3) 10)&lt;br /&gt;         ((= kinds-of-coins 4) 25)&lt;br /&gt;         ((= kinds-of-coins 5) 50)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Running the code with the specified input shows us how many ways there are to make change for 11 cents with five coins.&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;&amp;gt; (count-change 11)&lt;br /&gt;4&lt;br /&gt;&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;A quick scan of the code shows that the &lt;code&gt;cc&lt;/code&gt; procedure contains two recursive calls to itself, resulting in the tree-shaped process structure mentioned in the question.  Leaf nodes of the tree are reached when the base cases are met, that is when the amount is less than or equal to zero, or when the kinds of coins remaining reaches zero.&lt;br /&gt;&lt;br /&gt;When a node splits, its left-hand child is passed the same amount and one fewer kinds of coins.  The right-hand child is passed an amount that is reduced by the highest-denomination coin available to its parent node, and the same number of kinds of coins. (Click the images enlarge.)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PnLYRqe0k9g/SzGivYYCCUI/AAAAAAAAAQU/H-uwa5yg0f0/s1600-h/count-change-diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 246px; height: 320px;" src="http://3.bp.blogspot.com/_PnLYRqe0k9g/SzGivYYCCUI/AAAAAAAAAQU/H-uwa5yg0f0/s320/count-change-diagram.png" alt="" id="BLOGGER_PHOTO_ID_5418290761584216386" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I've color-coded the nodes of the tree.  White nodes are those leaf nodes that evaluate to 0, blue nodes are those leaf nodes that evaluate to 1 and contribute to the final answer.  The yellow nodes are those that branch recursively.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Orders of growth&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The exercise also asks us to find the orders of growth of the space and number of steps used by the &lt;code&gt;count-change&lt;/code&gt; process as the amount to be changed increases.  (Note that we are not really concerned with the orders of growth as the number of kinds of coins grows, only the amount to be changed.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Space &lt;/span&gt;- As we saw in the Fibonacci procedure in section 1.2.2, the space required by the &lt;code&gt;count-change&lt;/code&gt; procedure grows linearly with the input.  The space required is proportional to the maximum depth of the tree.  At any point in the computation we only need to keep track of the nodes above the current node.&lt;br /&gt;&lt;br /&gt;Since the height of the tree is proportional to the amount to be changed, the order of growth of the space required by the &lt;code&gt;count-change&lt;/code&gt; procedure is O(n).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Number of steps&lt;/span&gt; - The diagram illustrates that this procedure, much like the recursive procedure for computing Fibonacci numbers that we saw before, in not very efficient.  Much of the computation being done is repeated.&lt;br /&gt;&lt;br /&gt;If we look closely at a call to &lt;code&gt;cc&lt;/code&gt; where &lt;code&gt;kinds-of-coins&lt;/code&gt; is equal to one, we can see each call generates two more calls until we reach a terminal node.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PnLYRqe0k9g/SzGjJiyaxHI/AAAAAAAAAQc/Ml7-HqFteeY/s1600-h/count-change-11-1-diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 122px; height: 320px;" src="http://4.bp.blogspot.com/_PnLYRqe0k9g/SzGjJiyaxHI/AAAAAAAAAQc/Ml7-HqFteeY/s320/count-change-11-1-diagram.png" alt="" id="BLOGGER_PHOTO_ID_5418291211055842418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;If we define the function T(a, k) to be the number of calls to &lt;code&gt;cc&lt;/code&gt; generated by calling &lt;code&gt;(cc n k)&lt;/code&gt;, where n is the amount and k is the number of kinds of coins, then&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 1) = 2n + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;or in Big-O notation,&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 1) = &lt;span style="font-weight: bold;"&gt;O(n)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now let's take a look at a partial graph of a call to &lt;code&gt;(cc 50 2)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_PnLYRqe0k9g/SzGjXPesT6I/AAAAAAAAAQk/R1ourb2qVIc/s1600-h/count-change-50-2-diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 191px;" src="http://4.bp.blogspot.com/_PnLYRqe0k9g/SzGjXPesT6I/AAAAAAAAAQk/R1ourb2qVIc/s320/count-change-50-2-diagram.png" alt="" id="BLOGGER_PHOTO_ID_5418291446391000994" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;There are two interesting things to point out here.  First, there are n/5 calls to &lt;code&gt;cc&lt;/code&gt; made where k = 2 kinds of coins (look down the right hand side of the diagram above).  This is because each call is made with 5 cents less in the amount argument until a terminal node is reached.  The second interesting thing is that each of these n/5 calls to &lt;code&gt;(cc n 2)&lt;/code&gt; generates an entire &lt;code&gt;(cc n 1)&lt;/code&gt; subtree.&lt;br /&gt;&lt;br /&gt;That means that&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 2) = (n/5) * 2n + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;and because of the multiplication of terms&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 2) = &lt;span style="font-weight: bold;"&gt;O(n&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;2&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Similarly, if we look at the graph of &lt;code&gt;(cc 50 3)&lt;/code&gt; we can see n/10 calls to &lt;code&gt;cc&lt;/code&gt; where k = 3, each of which generates its own &lt;code&gt;(cc n 2)&lt;/code&gt; subtree.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PnLYRqe0k9g/SzGjhCgNl2I/AAAAAAAAAQs/-Q-f8Q-sCdA/s1600-h/count-change-50-3-diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 223px;" src="http://1.bp.blogspot.com/_PnLYRqe0k9g/SzGjhCgNl2I/AAAAAAAAAQs/-Q-f8Q-sCdA/s320/count-change-50-3-diagram.png" alt="" id="BLOGGER_PHOTO_ID_5418291614706407266" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;From this we find that&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 3) = &lt;span style="font-weight: bold;"&gt;O(n&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;3&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Finally, it's easy enough to show that we'll get the same pattern when k = 4 and k = 5.  The n/50 nodes generated when k = 5 each generate n/25 nodes with k = 4, each of which generates a node where k = 3.&lt;br /&gt;&lt;br /&gt;And so the final answer we arrive at for the time complexity of the &lt;code&gt;count-change&lt;/code&gt; procedure with five kinds of coins is&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;T(n, 5) = &lt;span style="font-weight: bold;"&gt;O(n&lt;/span&gt;&lt;sup style="font-weight: bold;"&gt;5&lt;/sup&gt;&lt;span style="font-weight: bold;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Related:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For links to all of the SICP lecture notes and exercises that I've done so far, see &lt;a href="http://www.billthelizard.com/2009/10/sicp-challenge.html"&gt;The SICP Challenge&lt;/a&gt;. &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9182705499898252496-5439647743608276098?l=www.billthelizard.com' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/5439647743608276098/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=5439647743608276098" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5439647743608276098?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5439647743608276098?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2009/12/sicp-exercise-114-counting-change.html" title="SICP Exercise 1.14: Counting change" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10577967119734468027" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_PnLYRqe0k9g/SzGivYYCCUI/AAAAAAAAAQU/H-uwa5yg0f0/s72-c/count-change-diagram.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
