<?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:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;C0cEQXYyfSp7ImA9WhFTGEw.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496</id><updated>2013-06-09T16:50:00.895-04:00</updated><category term="web" /><category term="bugs" /><category term="books" /><category term="interesting" /><category term="dotted-tail" /><category term="fermat" /><category term="open source" /><category term="pmd" /><category term="practice" /><category term="carroll" /><category term="css" /><category term="derivative" /><category term="perfect numbers" /><category term="probability" /><category term="c++" /><category term="float" /><category term="bias" /><category term="integral" /><category term="simulation" /><category term="scheme" /><category term="halloween" /><category term="table" /><category term="reading" /><category term="snippets" /><category term="visualization" /><category term="big-o" /><category term="threads" /><category term="dvorak" /><category term="java" /><category term="double" /><category term="logic" /><category term="security" /><category term="licenses" /><category term="fractals" /><category term="schneier" /><category term="coin toss" /><category term="links" /><category term="fibonacci" /><category term="misc" /><category term="c" /><category term="geometry" /><category term="pair programming" /><category term="algebra" /><category term="goldbach" /><category term="software" /><category term="html" /><category term="vectors" /><category term="puzzles" /><category term="qwerty" /><category term="mersenne" /><category term="statistics" /><category term="testing" /><category term="chess" /><category term="crypto" /><category term="24" /><category term="horner" /><category term="randomness" /><category term="statitstics" /><category term="curiosity" /><category term="answers" /><category term="education" /><category term="technology" /><category term="blog spam" /><category term="benford" /><category term="cout" /><category term="pi" /><category term="lists" /><category term="conway" /><category term="map" /><category term="solutions" /><category term="data visualization" /><category term="unsolved" /><category term="python" /><category term="trees" /><category term="blowfish" /><category term="windows" /><category term="sicp" /><category term="productivity" /><category term="learning" /><category term="usability" /><category term="science" /><category term="gauss" /><category term="golden ratio" /><category term="math" /><category term="dodgson" /><category term="programming" /><category term="experience" /><category term="calculus" /><category term="CSV" /><category term="precision" /><category term="simpson" /><category term="letter frequency" /><category term="hints" /><category term="netbeans" /><category term="proof" /><category term="time" /><category term="sequences" /><category term="pascal" /><category term="primes" /><category term="captcha" /><category term="hello world" /><category term="data structures" /><category term="matrix" /><category term="euler" /><category term="exercises" /><category term="languages" /><category term="miller-rabin" /><category term="quotes" /><category term="gambling" /><category term="chaos" /><category term="numbers" /><category term="equals" /><category term="questions" /><category term="sets" /><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="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><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>164</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" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DkcDSHozfCp7ImA9WhBUE0o.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-1675485678866526614</id><published>2013-04-30T22:07:00.000-04:00</published><updated>2013-04-30T22:07:59.484-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-30T22:07:59.484-04: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 2.66: Sets and information retrieval</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_Temp_255"&gt;2.3.3 Sets and information retrieval&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The final part of section 2.3.3 asks us to consider a database that contains records, each of which has a key and some data.  If the database is represented as an unordered list, a record can be looked up by its key using the following procedure.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (lookup given-key set-of-records)
  (cond ((null? set-of-records) false)
        ((equal? given-key (key (car set-of-records)))
         (car set-of-records))
        (else (lookup given-key (cdr set-of-records)))))
&lt;/pre&gt;  &lt;br /&gt;
We can define simple procedures for making a record out of a key and its data, and for extracting the key and data from an existing record in order to test the procedure above.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (key record) (car record))
(define (data record) (cdr record))
(define (make-record key data) (cons key data))

(define database
  (list (make-record 1 'Bill)
        (make-record 2 'Joe)
        (make-record 3 'Frank)
        (make-record 4 'John)))
  
&gt; (lookup 3 database)
'(3 . Frank)
&gt; (data (lookup 1 database))
'Bill
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Exercise 2.66&lt;/b&gt; asks us to implement the &lt;code&gt;lookup&lt;/code&gt; procedure for the case where the set of records is structured as a binary tree, ordered by the numerical values of the keys.&lt;br /&gt;
&lt;br /&gt;
We can start by including the &lt;code&gt;list-&gt;tree&lt;/code&gt; and &lt;code&gt;partial-tree&lt;/code&gt; procedures given for &lt;a href="http://www.billthelizard.com/2013/03/sicp-263-265-sets-as-binary-trees.html"&gt;exercise 2.64&lt;/a&gt;, along with a few required supporting procedures.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (entry tree) (car tree))
(define (left-branch tree) (cadr tree))
(define (right-branch tree) (caddr tree))
(define (make-tree entry left right)
  (list entry left right))
  
(define (list-&gt;tree elements)
  (car (partial-tree elements (length elements))))

(define (partial-tree elts n)
  (if (= n 0)
      (cons '() elts)
      (let ((left-size (quotient (- n 1) 2)))
        (let ((left-result (partial-tree elts left-size)))
          (let ((left-tree (car left-result))
                (non-left-elts (cdr left-result))
                (right-size (- n (+ left-size 1))))
            (let ((this-entry (car non-left-elts))
                  (right-result (partial-tree (cdr non-left-elts)
                                              right-size)))
              (let ((right-tree (car right-result))
                    (remaining-elts (cdr right-result)))
                (cons (make-tree this-entry left-tree right-tree)
                      remaining-elts))))))))
&lt;/pre&gt;       &lt;br /&gt;
This makes it easier to convert the existing database to one structured as a binary tree.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&gt; (define tree-db (list-&gt;tree database))
&gt; tree-db
'((2 . Joe) ((1 . Bill) () ()) ((3 . Frank) () ((4 . John) () ())))
&lt;/pre&gt;&lt;br /&gt;
Finally, we can write the new implementation of &lt;code&gt;lookup&lt;/code&gt; using &lt;code&gt;element-of-set?&lt;/code&gt; as a guide.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (lookup given-key set-of-records)
  (cond ((null? set-of-records) #f)
        ((= given-key (key (car set-of-records)))
         (car set-of-records))
        ((&lt; given-key (key (car set-of-records)))
         (lookup given-key (left-branch set-of-records)))
        ((&gt; given-key (key (car set-of-records)))
         (lookup given-key (right-branch set-of-records)))))

&gt; (lookup 3 tree-db)
'(3 . Frank)
&gt; (lookup 1 tree-db)
'(1 . Bill)
&gt; (lookup 5 tree-db)
#f
&gt; (data (lookup 2 tree-db))
'Joe
&lt;/pre&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;br /&gt;
</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/1675485678866526614/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=1675485678866526614" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1675485678866526614?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1675485678866526614?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2013/04/sicp-266-sets-and-information-retrieval.html" title="SICP 2.66: Sets and information retrieval" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;DUUNQXg7fCp7ImA9WhBXEUg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-2541113179306336317</id><published>2013-03-24T16:29:00.000-04:00</published><updated>2013-03-24T16:34:50.604-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-24T16:34:50.604-04: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 2.63 - 2.65: Sets as binary trees</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.3"&gt;2.3.3 Example: Representing Sets&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
So far in this section we've looked at two ways of representing sets.  First as unordered lists, then as ordered lists.  Now we'll look at how we can represent sets as binary trees, and we'll see what advantages this representation has over ordered lists.&lt;br /&gt;
&lt;br /&gt;
Each node of a tree holds one element of the set, called the "entry" at that node, and a link to each of two other (possibly empty) nodes. The "left" link points to elements smaller than the one at the node, and the "right" link to elements greater than the one at the node.  The same set may be represented by a number of different trees. The only requirements for a valid representation is that all elements in the left subtree must be smaller than the node entry and all elements in the right subtree be must be larger than the node entry.  Figure 2.16 in the text shows several valid tree representations of the same set of values.&lt;br /&gt;
&lt;br /&gt;
&lt;img border="0" src="http://mitpress.mit.edu/sicp/full-text/book/ch2-Z-G-51.gif" /&gt;&lt;br /&gt;
&lt;br /&gt;
Recall that for an ordered set of n elements, we had to search through (on average) n/2 elements to locate a particular value.  We do this by searching through the elements in order.  The advantage of a tree representation is that we can cut this effort down to log n if the tree is balanced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.63&lt;/b&gt; asks us if the following two procedures produce the same results for every tree, and if not how they differ.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (tree-&gt;list-1 tree)
  (if (null? tree)
      '()
      (append (tree-&gt;list-1 (left-branch tree))
              (cons (entry tree)
                    (tree-&gt;list-1 (right-branch tree))))))
     
(define (tree-&gt;list-2 tree)
  (define (copy-to-list tree result-list)
    (if (null? tree)
        result-list
        (copy-to-list (left-branch tree)
                      (cons (entry tree)
                            (copy-to-list (right-branch tree)
                                          result-list)))))
  (copy-to-list tree '()))
&lt;/pre&gt;&lt;br /&gt;
The &lt;code&gt;tree-&gt;list-1&lt;/code&gt; procedure checks to see if the tree passed in is &lt;code&gt;null&lt;/code&gt;, and if so returns an empty list.  If the tree is not &lt;code&gt;null&lt;/code&gt;, it creates a list by appending the left branch of the tree, the element at the root node, and the right branch of the tree.  Elements of the left and right branches are flattened into lists using recursive calls to &lt;code&gt;tree-&gt;list-1&lt;/code&gt;.  The &lt;code&gt;tree-&gt;list-2&lt;/code&gt; procedure defines a helper function &lt;code&gt;copy-to-list&lt;/code&gt; that takes the tree and a &lt;code&gt;result-list&lt;/code&gt; as arguments.  When the tree is &lt;code&gt;null&lt;/code&gt;, it returns the &lt;code&gt;result-list&lt;/code&gt; that was passed in.  The &lt;code&gt;copy-to-list&lt;/code&gt; helper function also uses recursive calls to the left and right branches of the tree while building the final &lt;code&gt;result list&lt;/code&gt;.  These two procedures will produce the same results for every tree.&lt;br /&gt;
&lt;br /&gt;
We're asked to test the two procedures on the trees in figure 2.16.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define tree1 '(7 (3 (1 () ()) (5 () ())) (9 () (11 () ()))))
(define tree2 '(3 (1 () ()) (7 (5 () ()) (9 () (11 () ())))))
(define tree3 '(5 (3 (1 () ()) ()) (9 (7 () ()) (11 () ()))))

&gt; (tree-&gt;list-1 tree1)
'(1 3 5 7 9 11)
&gt; (tree-&gt;list-2 tree1)
'(1 3 5 7 9 11)
&gt; (tree-&gt;list-1 tree2)
'(1 3 5 7 9 11)
&gt; (tree-&gt;list-2 tree2)
'(1 3 5 7 9 11)
&gt; (tree-&gt;list-1 tree3)
'(1 3 5 7 9 11)
&gt; (tree-&gt;list-2 tree3)
'(1 3 5 7 9 11)
&lt;/pre&gt;&lt;br /&gt;
We can see from these results that both procedures return an in-order traversal for every tree.&lt;br /&gt;
&lt;br /&gt;
We're also asked if the two procedures have the same order of growth for a balanced tree, and if not, which one grows more slowly?&lt;br /&gt;
&lt;br /&gt;
We can see from the results above and from inspecting the two procedures that each node of the tree is visited one time by each algorithm.  What happens at each of those n steps is subtly different though.  The second procedure simply calls &lt;code&gt;cons&lt;/code&gt; at each step, which we'll assume is a constant-time operation, so the &lt;code&gt;tree-&gt;list-2&lt;/code&gt; procedure has a time complexity of $O(n)$.  The first procedure calls &lt;code&gt;append&lt;/code&gt; at each step, which we saw in section 2.2.1 has the following definition:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (append list1 list2)
  (if (null? list1)
      list2
      (cons (car list1) (append (cdr list1) list2))))
&lt;/pre&gt;&lt;br /&gt;
From this definition we can see that the order of growth of &lt;code&gt;append&lt;/code&gt; is proportional to the first list argument that's passed in.  In the case of &lt;code&gt;tree-&gt;list-1&lt;/code&gt;, the first list argument is the left branch of the tree, which is about half of a node's elements for a balanced tree.  This means that for each recursive call, approximately half of the number of nodes will be in the first list argument as in the previous call.  Since the number of elements is cut in half on each of the n calls to &lt;code&gt;append&lt;/code&gt;, the &lt;code&gt;tree-&gt;list-1&lt;/code&gt; procedure has a complexity of $O(n log n)$ for a balanced tree.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.64&lt;/b&gt; introduces the &lt;code&gt;list-&gt;tree&lt;/code&gt; procedure, which converts an ordered list to a balanced binary tree using the helper procedure &lt;code&gt;partial-tree&lt;/code&gt; that takes as arguments an integer n and list of at least n elements and constructs a balanced tree containing the first n elements of the list.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (list-&gt;tree elements)
  (car (partial-tree elements (length elements))))

(define (partial-tree elts n)
  (if (= n 0)
      (cons '() elts)
      (let ((left-size (quotient (- n 1) 2)))
        (let ((left-result (partial-tree elts left-size)))
          (let ((left-tree (car left-result))
                (non-left-elts (cdr left-result))
                (right-size (- n (+ left-size 1))))
            (let ((this-entry (car non-left-elts))
                  (right-result (partial-tree (cdr non-left-elts)
                                              right-size)))
              (let ((right-tree (car right-result))
                    (remaining-elts (cdr right-result)))
                (cons (make-tree this-entry left-tree right-tree)
                      remaining-elts))))))))
&lt;/pre&gt;&lt;br /&gt;
First we're asked to explain how &lt;code&gt;partial-tree&lt;/code&gt; works, then draw the tree produced by &lt;code&gt;list-&gt;tree&lt;/code&gt; for the list &lt;code&gt;(1 3 5 7 9 11)&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;partial-tree&lt;/code&gt; procedure works by dividing the list into three parts, a center element (the root node of the tree), everything before the center element, and everything after the center element.  All the elements before the center element are then passed to a recursive call to &lt;code&gt;partial-tree&lt;/code&gt; to create the left branch of the tree, and all the elements after the center element are passed recursively to &lt;code&gt;partial-tree&lt;/code&gt; to create the right branch.  These recursive call continue until no elements are remaining, and the balanced binary tree is assembled.&lt;br /&gt;
&lt;br /&gt;
The tree produced by &lt;code&gt;list-&gt;tree&lt;/code&gt; for the list &lt;code&gt;(1 3 5 7 9 11)&lt;/code&gt; is:&lt;br /&gt;
&lt;br /&gt;
&lt;img border="0" src="http://4.bp.blogspot.com/-X820NpHkbDg/UU9eWnCg4uI/AAAAAAAABE4/2gFD0_VQYZc/s320/balanced_tree.png" /&gt;&lt;br /&gt;
&lt;br /&gt;
To verify this, we can simply call the procedure.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&gt; (list-&gt;tree '(1 3 5 7 9 11))
'(5 (1 () (3 () ())) (9 (7 () ()) (11 () ())))
&lt;/pre&gt;&lt;br /&gt;
Next we're asked what is the order of growth in the number of steps required by &lt;code&gt;list-&gt;tree&lt;/code&gt; to convert a list of n elements?  The procedure only needs to visit each element of the list once, and it only performs a &lt;code&gt;cons&lt;/code&gt; for each element it visits, so the number of steps is proportional to the size of the list, or $O(n)$.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.65&lt;/b&gt; asks us to use the results of the previous two exercises to give $O(n)$ implementations of &lt;code&gt;union-set&lt;/code&gt; and &lt;code&gt;intersection-set&lt;/code&gt; for sets implemented as (balanced) binary trees.&lt;br /&gt;
&lt;br /&gt;
We implemented &lt;code&gt;union-set&lt;/code&gt; for the unordered list representation of sets back in &lt;a href="http://www.billthelizard.com/2012/05/sicp-259-260-sets-as-unordered-lists.html"&gt;exercise 2.59&lt;/a&gt;.  This implementation had to check all elements of one set for each element of the other, so it's complexity was $O(n^2)$, quite poor.  We improved on this in &lt;a href="http://www.billthelizard.com/2012/07/sicp-261-262-sets-as-ordered-lists.html"&gt;exercise 2.62&lt;/a&gt; when we wrote an implementation of &lt;code&gt;union-set&lt;/code&gt; for the ordered list representation of sets, which was $O(n)$.  The text supplied a similar implementation of &lt;code&gt;intersection-set&lt;/code&gt; that was also $O(n)$.  We could use these ordered set implementations as a guide to writing efficient implementations of &lt;code&gt;union-set&lt;/code&gt; and &lt;code&gt;intersection-set&lt;/code&gt; for balanced binary trees, but that wouldn't require the results of the previous two exercises.  Instead, we can use the $O(n)$ implementations of all of the procedures we've built so far to perform the following steps:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Convert the balanced binary trees to ordered lists.&lt;/li&gt;
&lt;li&gt;Perform the desired operation (&lt;code&gt;union-set&lt;/code&gt; or &lt;code&gt;intersection-set&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Convert the resulting ordered set back to a balanced binary tree.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (union-set tree1 tree2)
  (define (union-list set1 set2)
    (cond ((null? set1) set2)
          ((null? set2) set1)
          ((= (car set1) (car set2))
           (cons (car set1) (union-list (cdr set1) (cdr set2))))
          ((&lt; (car set1) (car set2))
           (cons (car set1) (union-list (cdr set1) set2)))
          (else (cons (car set2) (union-list set1 (cdr set2))))))
  (list-&gt;tree (union-list (tree-&gt;list-2 tree1)
                          (tree-&gt;list-2 tree2))))

(define (intersection-set tree1 tree2)
  (define (intersection-list set1 set2)
    (if (or (null? set1) (null? set2))
        '()    
        (let ((x1 (car set1)) (x2 (car set2)))
          (cond ((= x1 x2)
                 (cons x1
                       (intersection-list (cdr set1)
                                          (cdr set2))))
                ((&lt; x1 x2)
                 (intersection-list (cdr set1) set2))
                ((&lt; x2 x1)
                 (intersection-list set1 (cdr set2)))))))
  (list-&gt;tree (intersection-list (tree-&gt;list-2 tree1)
                                 (tree-&gt;list-2 tree2))))
&lt;/pre&gt;&lt;br /&gt;
In the implementations above, I've just defined the earlier ordered set implementations of &lt;code&gt;union-set&lt;/code&gt; and &lt;code&gt;intersection-set&lt;/code&gt; as helper functions named &lt;code&gt;union-list&lt;/code&gt; and &lt;code&gt;intersection-list&lt;/code&gt;.  With these helper functions, all &lt;code&gt;union-set&lt;/code&gt; and &lt;code&gt;intersection-set&lt;/code&gt; need to do is convert from tree to list and back from list to tree.  We can define a few balanced trees to test that these new implementations work as expected.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&gt; (define evens (list-&gt;tree '(0 2 4 6 8 10)))
&gt; (define odds (list-&gt;tree '(1 3 5 7 9)))
&gt; (define primes (list-&gt;tree '(2 3 5 7 11 13 17 19)))
&gt;
&gt; evens
'(4 (0 () (2 () ())) (8 (6 () ()) (10 () ())))
&gt; odds
'(5 (1 () (3 () ())) (7 () (9 () ())))
&gt; primes
'(7 (3 (2 () ()) (5 () ())) (13 (11 () ()) (17 () (19 () ()))))
&gt;
&gt; (union-set odds evens)
'(5
  (2 (0 () (1 () ())) (3 () (4 () ())))
  (8 (6 () (7 () ())) (9 () (10 () ()))))
&gt; (union-set odds odds)
'(5 (1 () (3 () ())) (7 () (9 () ())))
&gt; (intersection-set evens primes)
'(2 () ())
&gt; (intersection-set odds primes)
'(5 (3 () ()) (7 () ()))
&gt; (intersection-set odds evens)
'()
&lt;/pre&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;br /&gt;
</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/2541113179306336317/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=2541113179306336317" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2541113179306336317?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2541113179306336317?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2013/03/sicp-263-265-sets-as-binary-trees.html" title="SICP 2.63 - 2.65: Sets as binary trees" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-X820NpHkbDg/UU9eWnCg4uI/AAAAAAAABE4/2gFD0_VQYZc/s72-c/balanced_tree.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkICRn85fCp7ImA9WhJVFUg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8846359505342374025</id><published>2012-09-01T22:58:00.005-04:00</published><updated>2012-09-02T00:02:47.124-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-02T00:02:47.124-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><title>12 (Really) Controversial Programming Opinions</title><content type="html">A few days ago, &lt;a href="http://programmers.stackexchange.com/users/25936/yannis-rizos"&gt;Yannis Rizos&lt;/a&gt; posted &lt;a href="http://programmers.blogoverflow.com/2012/08/20-controversial-programming-opinions/"&gt;20 controversial programming opinions&lt;/a&gt; on the Programmers Community Blog.  Judging by the comments on the blog, and on &lt;a href="http://redd.it/z0nng"&gt;reddit&lt;/a&gt; and &lt;a href="http://news.ycombinator.com/item?id=4448327"&gt;Hacker News&lt;/a&gt;, none of these opinions are considered all that controversial by the programming community at large.  The problem stems from the fact that the opinions posted were selected from among the top-voted answers to &lt;a href="http://stackoverflow.com/users/22656/jon-skeet"&gt;Jon Skeet’s&lt;/a&gt; question &lt;a href="http://stackoverflow.com/q/406760/1288"&gt;What’s your most controversial programming opinion?&lt;/a&gt;, originally asked on Stack Overflow on January 2, 2009.  People seem to have voted for answers they strongly agreed with, making those top answers some of the &lt;span style="font-style:italic;"&gt;least&lt;/span&gt; controversial opinions you could gather.&lt;br /&gt;&lt;br /&gt;I decided to take a different approach.  What follows are some of the opinions that I found near the middle or at the end of the list.  I tried to pick only answers where the author made an attempt at supporting their opinion, but as you can see some of these opinions were downvoted more heavily than they were upvoted by the Stack Overflow community.  (I'll add that my own "controversial" opinion is that Jon's question is perhaps the best argument we have that these types of opinion polls simply do not work on Stack Overflow.)&lt;br /&gt;&lt;br style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;1. Two lines of code is too many.&lt;/span&gt; (+20/-32) by &lt;a href="http://stackoverflow.com/users/5314/jay-bazuzi"&gt;Jay Bazuzi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If a method has a second line of code, it is a code smell. Refactor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. If it's not native, it's not really programming&lt;/span&gt; (+5/-15) by &lt;a href="http://stackoverflow.com/users/32914/mason-wheeler"&gt;Mason Wheeler&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By definition, a program is an entity that is run by the computer. It talks directly to the CPU and the OS. Code that does not talk directly to the CPU and the OS, but is instead run by some other program that does talk directly to the CPU and the OS, is not a program; it's a script. &lt;a href="http://stackoverflow.com/a/816215/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. The "While" construct should be removed from all programming languages.&lt;/span&gt; (+6/-14) by &lt;a href="http://stackoverflow.com/users/1726/seanyboy"&gt;seanyboy&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can easily replicate While using "Repeat" and a boolean flag, and I just don't believe that it's useful to have the two structures. In fact, I think that having both "Repeat...Until" and "While..EndWhile" in a language confuses new programmers.  &lt;a href="http://stackoverflow.com/a/406799/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Copy/Pasting is not an antipattern, it fact it helps with not making more bugs&lt;/span&gt; (+4/-5) by &lt;a href="http://stackoverflow.com/users/20128/serg"&gt;serg&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My rule of thumb - typing only something that cannot be copy/pasted. If creating similar method, class, or file - copy existing one and change what's needed. (I am not talking about duplicating a code that should have been put into a single method).  &lt;a href="http://stackoverflow.com/a/1651203/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;5. Developing on .NET is not programming. Its just stitching together other people's code.&lt;/span&gt; (+7/-5) by &lt;a href="http://stackoverflow.com/users/34411/gerard"&gt;Gerard&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Having come from a coding background where you were required to know the hardware, and where this is still a vital requirements in my industry, I view high level languages as simply assembling someone else's work. Nothing essentially wrong with this, but is it 'programming'?  &lt;a href="http://stackoverflow.com/a/1225112/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;6. The use of try/catch exception handling is worse than the use of simple return codes and associated common messaging structures to ferry useful error messages.&lt;/span&gt; (+11/-3) by &lt;a href="http://stackoverflow.com/users/41898/einstein"&gt;Einstein&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Littering code with try/catch blocks is not a solution.&lt;br /&gt;&lt;br /&gt;Just passing exceptions up the stack hoping whats above you will do the right thing or generate an informative error is not a solution.  &lt;a href="http://stackoverflow.com/a/408257/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;7. Test Constantly&lt;/span&gt; (+15/-7) by &lt;a href="http://stackoverflow.com/users/39077/pj-davis"&gt;PJ Davis&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You have to write tests, and you have to write them FIRST. Writing tests changes the way you write your code. It makes you think about what you want it to actually do before you just jump in and write something that does everything except what you want it to do. &lt;a href="http://stackoverflow.com/a/410491/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;8. Object Oriented Programming is absolutely the worst thing that's ever happened to the field of software engineering.&lt;/span&gt; (+34/-14) by &lt;a href="http://stackoverflow.com/users/51101/breton"&gt;Breton&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The primary problem with OOP is the total lack of a rigorous definition that everyone can agree on. This easily leads to implementations that have logical holes in them, or language like Java that adhere to this bizarre religious dogma about what OOP means, while forcing the programmer into doing all these contortions and "design patterns" just to work around the limitations of a particular OOP system. &lt;a href="http://stackoverflow.com/a/408751/1288"&gt;Read more&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;9. C (or C++) should be the first programming language&lt;/span&gt; (+24/-5) by &lt;a href="http://stackoverflow.com/users/35364/hasen-j"&gt;hansen j&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first language should NOT be the easy one, it should be one that sets up the student's mind and prepare it for serious computer science.&lt;br /&gt;C is perfect for that, it forces students to think about memory and all the low level stuff, and at the same time they can learn how to structure their code (it has functions!)&lt;br /&gt;&lt;br /&gt;C++ has the added advantage that it really sucks :) thus the students will understand why people had to come up with Java and C#.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;10. Classes should fit on the screen.&lt;/span&gt; (+22/-7) by &lt;a href="http://stackoverflow.com/users/5314/jay-bazuzi"&gt;Jay Bazuzi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you have to use the scroll bar to see all of your class, your class is too big.&lt;br /&gt;&lt;br /&gt;Code folding and miniature fonts are cheating.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;11. Making invisible characters syntactically significant in python was a bad idea&lt;/span&gt; (+43/-5) by &lt;a href="http://stackoverflow.com/users/85/paul-wicks"&gt;Paul Wicks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's distracting, causes lots of subtle bugs for novices and, in my opinion, wasn't really needed. About the only code I've ever seen that didn't voluntarily follow some sort of decent formatting guide was from first-year CS students. And even if code doesn't follow "nice" standards, there are plenty of tools out there to coerce it into a more pleasing shape.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;12. Singletons are not evil&lt;/span&gt; (+42/-7) by &lt;a href="http://stackoverflow.com/users/48552/steve"&gt;Steve&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is a place for singletons in the real world, and methods to get around them (i.e. monostate pattern) are simply singletons in disguise. For instance, a Logger is a perfect candidate for a singleton. Additionally, so is a message pump. My current app uses distributed computing, and different objects need to be able to send appropriate messages. There should only be one message pump, and everyone should be able to access it. The alternative is passing an object to my message pump everywhere it might be needed and hoping that a new developer doesn't new one up without thinking and wonder why his messages are going nowhere. The uniqueness of the singleton is the most important part, not its availability. The singleton has its place in the world.&lt;br /&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8846359505342374025/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8846359505342374025" title="22 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8846359505342374025?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8846359505342374025?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/09/12-really-controversial-programming.html" title="12 (Really) Controversial Programming Opinions" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>22</thr:total></entry><entry gd:etag="W/&quot;DkACQ3k6cSp7ImA9WhBXEUg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-1938372276090178217</id><published>2012-07-01T19:16:00.000-04:00</published><updated>2013-03-24T15:52:42.719-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-24T15:52:42.719-04: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 2.61 - 2.62: Sets as ordered lists</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.3"&gt;2.3.3  Example: Representing Sets&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
In &lt;a href="http://www.billthelizard.com/2012/05/sicp-259-260-sets-as-unordered-lists.html"&gt;exercises 2.59 and 2.60&lt;/a&gt; we looked at how to represent sets as unordered lists.  In the next two we'll look at representing sets as ordered lists, and at what benefits we get from the new implementation.&lt;br /&gt;
&lt;br /&gt;
First, if elements in a set are guaranteed to be in order, we can improve the performance of &lt;code&gt;element-of-set&lt;/code&gt; by returning false as soon as we encounter an element of the set that's less than the value that we're looking for.  All of the remaining elements are guaranteed to be smaller as well.  This saves us on average half the number of comparisons from the previous implementation.

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (element-of-set? x set)
  (cond ((null? set) false)
        ((= x (car set)) true)
        ((&amp;lt; x (car set)) false)
        (else (element-of-set? x (cdr set)))))
&lt;/pre&gt;
We get a more impressive improvement from &lt;code&gt;intersection-set&lt;/code&gt;.  In the old implementation using unordered lists we had to compare every element of each set to every element in the other set.  This had a complexity of $O(n^2)$.  With the elements of both sets in order we can reduce that all the way down to $O(n)$.  This is possible due to the fact that if the car of one ordered set is smaller than the car of another ordered set, it has to be smaller than all the other elements and we can discard it right away.

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (intersection-set set1 set2)
  (if (or (null? set1) (null? set2))
      '()    
      (let ((x1 (car set1)) (x2 (car set2)))
        (cond ((= x1 x2)
               (cons x1
                     (intersection-set (cdr set1)
                                       (cdr set2))))
              ((&amp;lt; x1 x2)
               (intersection-set (cdr set1) set2))
              ((&amp;lt; x2 x1)
               (intersection-set set1 (cdr set2)))))))
&lt;/pre&gt;
&lt;b&gt;Exercise 2.61&lt;/b&gt; asks us to give an implementation of &lt;code&gt;adjoin-set&lt;/code&gt; using the ordered representation.  Like &lt;code&gt;element-of-set?&lt;/code&gt;, our implementation of &lt;code&gt;adjoin-set&lt;/code&gt; should require only half as many steps on average as the unordered representation.&lt;br /&gt;
&lt;br /&gt;
The original implementation of &lt;code&gt;adjoin-set&lt;/code&gt; made use of &lt;code&gt;element-of-set?&lt;/code&gt; to check and see if the new element was already a member of the set.  We no longer need to do this since we need to find the exact position in the set to insert the new element.  As we scan through the set looking for the right position, we can simply return the set if we encounter the element we're trying to place.

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (adjoin-set x set)
  (cond ((null? set) (cons x '()))
        ((= x (car set)) set)
        ((&amp;lt; x (car set)) (cons x set))
        ((&amp;gt; x (car set)) (cons (car set)
                               (adjoin-set x (cdr set))))))
&lt;/pre&gt;
There are several different conditions, and we need to cover them all.  First, since we're no longer using &lt;code&gt;element-of-set&lt;/code&gt;, we need to check to see if the set itself is null or empty.  Second, if the we encounter the element we're trying to add, we can just return the set.  Next, if the element we're adding is smaller than the first element of the set, we can simply &lt;code&gt;cons&lt;/code&gt; the new element to the beginning of the set.  Last, if the new element is greater than the first element of the set, we join the first element followed by the &lt;code&gt;adjoin-set&lt;/code&gt; of the new element and the rest of the set. 

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (adjoin-set 3 null)
(3)
&amp;gt; (adjoin-set 3 '())
(3)
&amp;gt; (adjoin-set 3 '(3 4 5))
(3 4 5)
&amp;gt; (adjoin-set 3 '(4 5 6))
(3 4 5 6)
&amp;gt; (adjoin-set 3 '(1 2 4 5))
(1 2 3 4 5)
&amp;gt; (adjoin-set 3 '(0 1 2))
(0 1 2 3)
&lt;/pre&gt;
Like &lt;code&gt;element-of-set?&lt;/code&gt;, this implementation should only scan through half the set on average before finding the correct insertion point for the new element.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.62&lt;/b&gt; asks us to give a $O(n)$ implementation of &lt;code&gt;union-set&lt;/code&gt; for sets represented as ordered lists.  Since the two sets are in order, we can simply step through each set comparing the first elements of each.  At each step we decide which of the first two elements to place in the resulting set.

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (union-set set1 set2)
  (cond ((null? set1) set2)
        ((null? set2) set1)
        ((= (car set1) (car set2))
         (cons (car set1) (union-set (cdr set1) (cdr set2))))
        ((&amp;lt; (car set1) (car set2))
         (cons (car set1) (union-set (cdr set1) set2)))
        (else (cons (car set2) (union-set set1 (cdr set2))))))
&lt;/pre&gt;
Anyone familiar with the &lt;a href="http://en.wikipedia.org/wiki/Merge_sort"&gt;mergesort algorithm&lt;/a&gt; will quickly recognize that this implementation of &lt;code&gt;union-set&lt;/code&gt; is almost exactly the same procedure as the merge subroutine.  It's purpose is to quickly merge two sorted lists into one.  The only difference is that the &lt;code&gt;union-set&lt;/code&gt; implementation above only keeps one copy of duplicate elements.

&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (define odds '(1 3 5 7))
&amp;gt; (define evens '(2 4 6 8))
&amp;gt; (define primes '(2 3 5 7))
&amp;gt; (union-set odds evens)
(1 2 3 4 5 6 7 8)
&amp;gt; (union-set odds primes)
(1 2 3 5 7)
&amp;gt; (union-set evens primes)
(2 3 4 5 6 7 8)
&lt;/pre&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/1938372276090178217/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=1938372276090178217" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1938372276090178217?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1938372276090178217?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/07/sicp-261-262-sets-as-ordered-lists.html" title="SICP 2.61 - 2.62: Sets as ordered lists" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CUQCQHs5eip7ImA9WhVbEkg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-5510007102925758554</id><published>2012-05-28T21:02:00.000-04:00</published><updated>2012-05-28T21:02:41.522-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-28T21:02:41.522-04: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 2.59 - 2.60: Sets as unordered lists</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.3"&gt;2.3.3&amp;nbsp; Example: Representing Sets&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Section 2.3.3 shows us several ways to represent sets in Scheme, starting with unordered sets.  To start, we define what a 'set' is by specifying the operations that are to be used on sets. These are:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;element-of-set?&lt;/code&gt; - a predicate function that determines whether a given element is a member of a set.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adjoin-set&lt;/code&gt; - takes an object and a set as arguments and returns the set that contains the elements of the original set and the adjoined object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;intersection-set&lt;/code&gt; - computes the intersection of two sets, which is the set containing only elements that appear in both arguments.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;union-set&lt;/code&gt; - computes the union of two sets, which is the set containing each element that appears in either argument.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
We represent a set as an unordered list by making sure no element appears more than once.  The text provides the following implementations for representing sets as unordered lists.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (element-of-set? x set)
  (cond ((null? set) false)
        ((equal? x (car set)) true)
        (else (element-of-set? x (cdr set)))))

(define (adjoin-set x set)
  (if (element-of-set? x set)
      set
      (cons x set)))

(define (intersection-set set1 set2)
  (cond ((or (null? set1) (null? set2)) '())
        ((element-of-set? (car set1) set2)        
         (cons (car set1)
               (intersection-set (cdr set1) set2)))
        (else (intersection-set (cdr set1) set2))))
&lt;/pre&gt;
&lt;br /&gt;
We can define a few lists to test and see how these procedures work together.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (define odds '(1 3 5 7))
&amp;gt; (define evens '(2 4 6 8))
&amp;gt; (define primes '(2 3 5 7))
&amp;gt; (element-of-set? 5 odds)
#t
&amp;gt; (element-of-set? 5 evens)
#f
&amp;gt; odds
(1 3 5 7)
&amp;gt; (adjoin-set 9 odds)
(9 1 3 5 7)
&amp;gt; (intersection-set odds evens)
()
&amp;gt; (intersection-set odds primes)
(3 5 7)
&amp;gt; (intersection-set evens primes)
(2)
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.59&lt;/b&gt; asks us to implement the &lt;code&gt;union-set&lt;/code&gt; operation for the unordered-list representation of sets.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (union-set set1 set2)
  (cond ((null? set1) set2)
        ((null? set2) set1)
        ((element-of-set? (car set1) set2) (union-set (cdr set1) set2))
        (else (cons (car set1) (union-set (cdr set1) set2)))))
&lt;/pre&gt;
&lt;br /&gt;
This implementation starts by checking to see if either set is null.  If so, the other set is returned immediately.  The procedure then checks to see if the first element of &lt;code&gt;set1&lt;/code&gt; is an element of &lt;code&gt;set2&lt;/code&gt;.  If so, that element is discarded from the first set, and the union of the remaining elements of &lt;code&gt;set1&lt;/code&gt; and &lt;code&gt;set2&lt;/code&gt; are returned.  If the first element of &lt;code&gt;set1&lt;/code&gt; is not an element of &lt;code&gt;set2&lt;/code&gt;, it is included in the list returned by the procedure.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (union-set odds evens)
(1 3 5 7 2 4 6 8)
&amp;gt; (union-set odds primes)
(1 2 3 5 7)
&amp;gt; (union-set evens primes)
(4 6 8 2 3 5 7)
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.60&lt;/b&gt; asks us what would need to change in the implementations above if we redefine 'set' to allow duplicate elements.  For example, the set {1, 2, 3} could be represented as the list (2 3 2 1 3 2 2).  We need to compare the efficiency of each of the new procedures with their original (non-duplicate) implementations.  The exercise also asks if there are applications where the new representation would be preferred over the original.&lt;br /&gt;
&lt;br /&gt;
The implementation of &lt;code&gt;element-of-set?&lt;/code&gt; doesn't need to change.  It returns &lt;code&gt;#t&lt;/code&gt; when it finds an element that matches the input element, otherwise it returns &lt;code&gt;#f&lt;/code&gt;.

The implementation of &lt;code&gt;adjoin-set&lt;/code&gt; is simplified by the new definition.  Since we no longer need to check to see if the input element already exists in the set, we can just &lt;code&gt;cons&lt;/code&gt; the element to the existing set.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (adjoin-set x set)
   (cons x set))
&lt;/pre&gt;
&lt;br /&gt;
Like &lt;code&gt;adjoin-set&lt;/code&gt;, &lt;code&gt;union-set&lt;/code&gt; is also simplified by allowing duplicate elements.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (union-set set1 set2) 
   (append set1 set2))
&lt;/pre&gt;
&lt;br /&gt;
We have an interesting choice when it comes to &lt;code&gt;intersection-set&lt;/code&gt;.  The intersection of two sets under the original (non-duplicate) definition doesn't seem like it requires any change in implementation since duplicates are now &lt;i&gt;allowed&lt;/i&gt;, not necessarily &lt;i&gt;required&lt;/i&gt;.  However, look what happens when you execute &lt;code&gt;intersection-set&lt;/code&gt; with duplicate elements in the first set vs. the second set.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (define primes '(2 3 5 7))
&amp;gt; (define twos '(2 2 2))
&amp;gt; (intersection-set primes twos)
(2)
&amp;gt; (intersection-set twos primes)
(2 2 2)
&lt;/pre&gt;
&lt;br /&gt;
The result is different depending on which set has duplicate elements.  This is because the original implementation checks each element of the first set independently to see if they're present in the second set.  When the first set contains duplicates, so will the result.  Since the instructions in the exercise are ambiguous (and being the typical lazy programmer that I am), I'm going to say that this implementation does not need to change.&lt;br /&gt;
&lt;br /&gt;
Since &lt;code&gt;element-of-set?&lt;/code&gt; and &lt;code&gt;intersection-set&lt;/code&gt; haven't changed, neither will their performance.  Since &lt;code&gt;adjoin-set&lt;/code&gt; and &lt;code&gt;union-set&lt;/code&gt; no longer need to check for duplicate elements, the performance of both of these procedures is improved.  The number of steps required by &lt;code&gt;adjoin-set&lt;/code&gt; has gone from $O(n)$ to $O(1)$.  The number of steps required by &lt;code&gt;union-set&lt;/code&gt; has gone from $O(n^2)$ to $O(n)$.&lt;br /&gt;
&lt;br /&gt;
The penalty that we pay for these performance improvements is that sets now require more memory to accommodate duplicate elements.  This representation would be preferred over the original in cases where we don't care about that added memory overhead, and where most of our operations are either &lt;code&gt;adjoin-set&lt;/code&gt; or &lt;code&gt;union-set&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/5510007102925758554/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=5510007102925758554" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5510007102925758554?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/5510007102925758554?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/05/sicp-259-260-sets-as-unordered-lists.html" title="SICP 2.59 - 2.60: Sets as unordered lists" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcAQHg6fSp7ImA9WhVVE0w.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-2544031183950184272</id><published>2012-05-06T11:27:00.000-04:00</published><updated>2012-05-06T11:27:21.615-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-06T11:27:21.615-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="software" /><category scheme="http://www.blogger.com/atom/ns#" term="licenses" /><title>Which Open Source License?</title><content type="html">I was doing a little research on open source software licenses with a student when I came across this flow chart.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/--EfX5P6Ny7Q/T6aSO_LdpNI/AAAAAAAAAgY/v-QFMmbP5As/s1600/OSS+License.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/--EfX5P6Ny7Q/T6aSO_LdpNI/AAAAAAAAAgY/v-QFMmbP5As/s640/OSS+License.png" width="496" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
I like the balance it strikes between being funny and still being at least somewhat useful and informative.&amp;nbsp; Credit for the original flowchart goes to the creators &lt;a href="https://twitter.com/#%21/dbentley"&gt;Dan Bentley&lt;/a&gt; and &lt;a href="https://twitter.com/#%21/therealfitz"&gt;Brian Fitzpatrick&lt;/a&gt;.&amp;nbsp; (Thanks to &lt;a href="https://twitter.com/#%21/jleedev"&gt;@jldeev&lt;/a&gt; for pointing me to the chart.)&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;
For a short break down of the key differences between some of the more popular software licenses, see Jeff Atwood's post &lt;a href="http://www.codinghorror.com/blog/2007/04/pick-a-license-any-license.html"&gt;Pick a License, Any License&lt;/a&gt; on the Coding Horror blog.&amp;nbsp; The main point to take away from the article is that if you don't explicitly declare a license on software you publish, your code is &lt;i&gt;copyrighted by default&lt;/i&gt;.&amp;nbsp; To use the code people have to contact you and ask permission.&amp;nbsp; So if you post a lot of code examples on your blog, take a few minutes to pick a license then add a notice to the footer of your site.&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/2544031183950184272/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=2544031183950184272" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2544031183950184272?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2544031183950184272?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/05/which-open-source-license.html" title="Which Open Source License?" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/--EfX5P6Ny7Q/T6aSO_LdpNI/AAAAAAAAAgY/v-QFMmbP5As/s72-c/OSS+License.png" height="72" width="72" /><thr:total>5</thr:total></entry><entry gd:etag="W/&quot;C0QNQ347eCp7ImA9WhVWEUg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-2763543399203550599</id><published>2012-04-22T23:23:00.000-04:00</published><updated>2012-04-22T23:23:12.000-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-22T23:23:12.000-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="derivative" /><category scheme="http://www.blogger.com/atom/ns#" term="calculus" /><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>SICP 2.56 - 2.58: Symbolic Differentiation</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.2"&gt;2.3.2&amp;nbsp; Example: Symbolic Differentiation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
This section of SICP presents an application of symbol manipulation in the form of the following procedure that performs symbolic differentiation of algebraic expressions.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((product? exp)
         (make-sum
           (make-product (multiplier exp)
                         (deriv (multiplicand exp) var))
           (make-product (deriv (multiplier exp) var)
                         (multiplicand exp))))
        (else
         (error "unknown expression type -- DERIV" exp))))
&lt;/pre&gt;
&lt;br /&gt;
The following supporting procedures are required by &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv&lt;/span&gt;.  Each one is explained in the text.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (variable? x) (symbol? x))

(define (same-variable? v1 v2)
  (and (variable? v1) (variable? v2) (eq? v1 v2)))

(define (make-sum a1 a2) (list '+ a1 a2))
(define (make-product m1 m2) (list '* m1 m2))

(define (sum? x)
  (and (pair? x) (eq? (car x) '+)))

(define (addend s) (cadr s))
(define (augend s) (caddr s))

(define (product? x)
  (and (pair? x) (eq? (car x) '*)))

(define (multiplier p) (cadr p))
(define (multiplicand p) (caddr p))
&lt;/pre&gt;
&lt;br /&gt;
With these definitions, we can perform differentiation on algebraic expressions in Scheme's familiar prefix notation.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(+ x 3) 'x)
(+ 1 0)
&amp;gt; (deriv '(* x y) 'x)
(+ (* x 0) (* 1 y))
&amp;gt; (deriv '(* (* x y) (+ x 3)) 'x)
(+ (* (* x y) (+ 1 0)) (* (+ (* x 0) (* 1 y)) (+ x 3)))
&lt;/pre&gt;
&lt;br /&gt;
This procedure returns results that are correct, but the expressions are not in their simplest form.  For example, instead of (+ 1 0) we'd like the procedure to simplify the expression to 1.  Similarly, the expression (+ (* x 0) (* 1 y)) can be simplified to y.

We only need to change the constructors &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-sum&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-product&lt;/span&gt; to simplify the resulting expressions.  We can change &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-sum&lt;/span&gt; so that if both its arguments are numbers, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-sum&lt;/span&gt; will return their sum. Also, if either of the arguments is 0, then make-sum will return the other summand (whether it's a number or a symbol).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (make-sum a1 a2)
  (cond ((=number? a1 0) a2)
        ((=number? a2 0) a1)
        ((and (number? a1) (number? a2)) (+ a1 a2))
        (else (list '+ a1 a2))))
&lt;/pre&gt;
&lt;br /&gt;
Similarly, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-product&lt;/span&gt; should return 0 if either of its arguments is 0, and if either of its arguments is 1 it should return the other argument.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (make-product m1 m2)
  (cond ((or (=number? m1 0) (=number? m2 0)) 0)
        ((=number? m1 1) m2)
        ((=number? m2 1) m1)
        ((and (number? m1) (number? m2)) (* m1 m2))
        (else (list '* m1 m2))))
&lt;/pre&gt;
&lt;br /&gt;
Both of these new implementations make use of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;=number?&lt;/span&gt; procedure to check whether an expression is equal to an expected value.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (=number? exp num)
  (and (number? exp) (= exp num)))
&lt;/pre&gt;
&lt;br /&gt;
Here's how the improved procedures work with the same three examples.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(+ x 3) 'x)
1
&amp;gt; (deriv '(* x y) 'x)
y
&amp;gt; (deriv '(* (* x y) (+ x 3)) 'x)
(+ (* x y) (* y (+ x 3)))
&lt;/pre&gt;
&lt;br /&gt;
The first two resulting expressions are now in simplest form.  The third is greatly improved, but could still be better.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.56&lt;/b&gt; asks us to extend the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;procedure to handle more kinds of expressions.  We're to implement the differentiation rule&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;
&amp;nbsp;$\frac{d(u^n)}{dx} = nu^{(n-1)} (\frac{du}{dx})$&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;
by adding a new clause to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;program and defining appropriate procedures &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exponentiation?&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;base&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exponent&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-exponentiation&lt;/span&gt;. (We'll use the symbol ** to denote exponentiation.) We'll also build in the rules that anything raised to the power 0 is 1 and any expression raised to the power 1 is the expression itself.

We can base the implementations of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exponentiation?&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;base&lt;/span&gt;, and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exponent &lt;/span&gt;on the corresponding procedures used for sums and products.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (exponentiation? x)
  (and (pair? x) (eq? (car x) '**)))

(define (base e) (cadr e))
(define (exponent e) (caddr e))&lt;/pre&gt;
&lt;br /&gt;
Similarly, our implementation of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-exponentiation&lt;/span&gt; will be based on the updated versions of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-sum&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;make-product&lt;/span&gt;, since we're going to build in two rules of exponentiation that will simplify resulting expressions.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (make-exponentiation base exponent)
  (cond ((=number? exponent 0) 1)
        ((=number? exponent 1) base)
        ((and (number? base) (number? exponent)) (expt base exponent))
        (else (list '** base exponent))))
&lt;/pre&gt;
&lt;br /&gt;
The last step before testing is to extend the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;procedure itself to recognize and handle exponentiation.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((product? exp)
         (make-sum
           (make-product (multiplier exp)
                         (deriv (multiplicand exp) var))
           (make-product (deriv (multiplier exp) var)
                         (multiplicand exp))))
        ((exponentiation? exp)
         (make-product
          (make-product (exponent exp)
                        (make-exponentiation
                         (base exp)
                         (make-sum (exponent exp) -1)))
          (deriv (base exp) var)))
        (else
         (error "unknown expression type -- DERIV" exp))))
&lt;/pre&gt;
&lt;br /&gt;
We can test the extended implementation of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;using an example from the beginning of the current section of the text.  "For example, if the arguments to the procedure are $ax^2 + bx + c$ and x, the procedure should return $2ax + b$."  I'll translate the expression to prefix notation in multiple steps so we can see the effect that each term has on the result.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(** x 2) 'x)
(* 2 x)
&amp;gt; (deriv '(* a (** x 2)) 'x)
(* a (* 2 x))
&amp;gt; (deriv '(+ (* a (** x 2)) (* b x)) 'x)
(+ (* a (* 2 x)) b)
&amp;gt; (deriv '(+ (+ (* a (** x 2)) (* b x)) c) 'x)
(+ (* a (* 2 x)) b)
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.57&lt;/b&gt; asks us to extend the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;program to handle sums and products with arbitrary numbers of (two or more) terms.  The third example above could be expressed as&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(deriv '(* x y (+ x 3)) 'x)&lt;/pre&gt;
&lt;br /&gt;
We'll do this by changing only the representation for sums and products, without changing the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv&lt;/span&gt; procedure itself. (For example, the addend of a sum would be the first term, and the augend would be the sum of the rest of the terms.)

We can change the representation for sums and products by changing only two procedures, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;augend &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multiplicand&lt;/span&gt;.  The original implementations of these procedures simply returned the second argument in a sum or product, respectively.  Instead of returning a single value or symbol, we'll need to modify these procedures so they can return an expression.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (augend s)
  (if (null? (cdddr s))
      (caddr s)
      (cons '+ (cddr s))))
&lt;/pre&gt;
&lt;br /&gt;
The new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;augend &lt;/span&gt;procedure first tests to see if the expression passed in has only two arguments by checking to see if its third argument is null.  If the expression has only two arguments, the second one is returned, just as it would have been in the original implementation.  Otherwise, if the expression has more than two arguments, all of the arguments following the first one are returned in a new sum expresssion.

The new implementation of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multiplicand &lt;/span&gt;is pretty much the same.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (multiplicand p)
  (if (null? (cdddr p))
      (caddr p)
      (cons '* (cddr p))))
&lt;/pre&gt;
&lt;br /&gt;
We can use the example from the text to test that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;deriv &lt;/span&gt;procedure works correctly with the new representations of sums and products.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(* x y (+ x 3)) 'x)
(+ (* x y) (* y (+ x 3)))
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;Exercise 2.58&lt;/b&gt; asks us to modify the differentiation program so that it works with ordinary mathematical notation (where + and * are infix rather than prefix operators).  Since the differentiation program is defined in terms of abstract data, we can modify it to work with different representations of expressions solely by changing the predicates, selectors, and constructors that define the representation of the algebraic expressions on which the differentiator is to operate.  We're to do this in two steps, a fully parenthesized version and a version that drops unnecessary parentheses:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;a.&lt;/b&gt;  Show how to do this in order to differentiate algebraic expressions presented in infix form, such as (x + (3 * (x + (y + 2)))). To simplify the task, assume that + and * always take two arguments and that expressions are fully parenthesized.&lt;br /&gt;
&lt;br /&gt;
We can solve the first part of the problem simply by changing the procedures that define how a sum is represented.&amp;nbsp; Instead of the + symbol appearing first in an expression, it will now appear second.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (make-sum a1 a2)
  (cond ((=number? a1 0) a2)
        ((=number? a2 0) a1)
        ((and (number? a1) (number? a2)) (+ a1 a2))
        (else (list a1 '+ a2))))

(define (sum? x)
  (and (pair? x) (eq? (cadr x) '+)))

(define (addend s) (car s))
(define (augend s) (caddr s))
&lt;/pre&gt;
&lt;br /&gt;
The definitions for products are equivalent.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (make-product m1 m2)
  (cond ((or (=number? m1 0) (=number? m2 0)) 0)
        ((=number? m1 1) m2)
        ((=number? m2 1) m1)
        ((and (number? m1) (number? m2)) (* m1 m2))
        (else (list m1 '* m2))))

(define (product? x)
  (and (pair? x) (eq? (cadr x) '*)))

(define (multiplier p) (car p))
(define (multiplicand p) (caddr p))
&lt;/pre&gt;
&lt;br /&gt;
We can test with a few simple examples before moving to the more complicated example given in the text.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(x + 3) 'x)
1
&amp;gt; (deriv '(x * y) 'x)
y
&amp;gt;  (deriv '(x + (3 * (x + (y + 2)))) 'x)
4
&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;b.&lt;/b&gt;  The problem becomes substantially harder if we allow standard algebraic notation, such as (x + 3 * (x + y + 2)), which drops unnecessary parentheses and assumes that multiplication is done before addition. Can you design appropriate predicates, selectors, and constructors for this notation such that our derivative program still works?&lt;br /&gt;
&lt;br /&gt;
Only a few additional changes are necessary in order to correctly interpret expressions where unnecessary parentheses are excluded.  In part a above we defined both the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;augend &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multiplicand &lt;/span&gt;of an expression using &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;caddr&lt;/span&gt;.  We were able to do this because we knew all expressions would be two parameters separated by an operator, and that the expression would be contained in parentheses.&lt;br /&gt;
&lt;br /&gt;
Since this is no longer the case, we now want the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;augend &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multiplicand &lt;/span&gt;procedures to return an entire subexpression, so we'd like to use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cddr&lt;/span&gt;.  The only problem with this is that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cddr&lt;/span&gt; always returns a list, so it will fail in those cases where the augend or multiplicand is a single value or symbol, as would be the case in fully-parenthesized expressions.  We can get around this limitation by introducing a procedure that will simplify sub-expressions of this form by returning a single value or symbol if that's all there is to an expression.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (simplify exp)
  (if (null? (cdr exp)) (car exp) exp))
&lt;/pre&gt;
&lt;br /&gt;
Now we can define &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;augend &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;multiplicand &lt;/span&gt;in terms of simplify and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cddr&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;(define (augend s) (simplify (cddr s)))
(define (multiplicand p) (simplify (cddr p)))
&lt;/pre&gt;
&lt;br /&gt;
We can test a few different expressions, starting with the example given.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(x + 3 * (x + y + 2)) 'x)
4
&amp;gt; (deriv '(x + 3 * (x + y + 2)) 'y)
3
&lt;/pre&gt;
&lt;br /&gt;
Finally, we should also test a few simpler cases to make sure our changes didn't break anything.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (deriv '(x + 3) 'x)
1
&amp;gt; (deriv '(x * y) 'x)
y
&amp;gt; (deriv '(x * y * (x + 3)) 'x)
((x * y) + (y * (x + 3)))
&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/2763543399203550599/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=2763543399203550599" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2763543399203550599?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/2763543399203550599?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/04/sicp-256-258-symbolic-differentiation.html" title="SICP 2.56 - 2.58: Symbolic Differentiation" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;DUMEQ387cSp7ImA9WhVTFkg.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-6485935559345325496</id><published>2012-03-01T21:48:00.002-05:00</published><updated>2012-03-01T22:03:22.109-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-01T22:03:22.109-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 2.53 - 2.55: Symbolic Data</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-16.html#%_sec_2.3.1"&gt;2.3.1  Quotation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This section of SICP introduces quotation, which gives us the ability to manipulate symbols as well as data values.  When we quote a symbol the interpreter returns the literal symbol instead of the value that the symbol points to.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (define a 1)&lt;br /&gt;&amp;gt; a&lt;br /&gt;1&lt;br /&gt;&amp;gt; (quote a)&lt;br /&gt;a&lt;/pre&gt;&lt;br /&gt;As a shorthand for &lt;code&gt;quote&lt;/code&gt; we can place a single quote symbol at the beginning of the object to be quoted.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; 'a&lt;br /&gt;a&lt;/pre&gt;&lt;br /&gt;We can also use quotation with compound objects.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (define x '(a b c))&lt;br /&gt;&amp;gt; x&lt;br /&gt;(a b c)&lt;br /&gt;&amp;gt; (car x)&lt;br /&gt;a&lt;/pre&gt;&lt;br /&gt;Finally, we're introduced to the primitive &lt;code&gt;eq?&lt;/code&gt;, which takes two symbols as arguments and tests whether they are the same (they consist of the same characters in the same order).  We're also shown how we can use &lt;code&gt;eq?&lt;/code&gt; to create a procedure &lt;code&gt;memq&lt;/code&gt; that takes two arguments, a symbol and a list. If the symbol is not contained in the list, then &lt;code&gt;memq&lt;/code&gt; returns false. Otherwise, it returns the sub-list that begins with the first occurrence of the symbol.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.53&lt;/span&gt; asks us what the interpreter would print in response to evaluating each of the following expressions?  See if you can predict what the output should be before trying each expression.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(list 'a 'b 'c)&lt;br /&gt;&lt;br /&gt;(list (list 'george))&lt;br /&gt;&lt;br /&gt;(cdr '((x1 x2) (y1 y2)))&lt;br /&gt;&lt;br /&gt;(cadr '((x1 x2) (y1 y2)))&lt;br /&gt;&lt;br /&gt;(pair? (car '(a short list)))&lt;br /&gt;&lt;br /&gt;(memq 'red '((red shoes) (blue socks)))&lt;br /&gt;&lt;br /&gt;(memq 'red '(red shoes blue socks))&lt;/pre&gt;&lt;br /&gt;The first expression just creates a list containing three symbols, so it should evaluate the same as &lt;code&gt;'(a b c)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; '(a b c)&lt;br /&gt;(a b c)&lt;br /&gt;&amp;gt; (list 'a 'b 'c)&lt;br /&gt;(a b c)&lt;/pre&gt;&lt;br /&gt;The second expression creates a list that contains a list that contains a symbol.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (list (list 'george))&lt;br /&gt;((george))&lt;/pre&gt;&lt;br /&gt;The third expression gets the &lt;code&gt;cdr&lt;/code&gt; of a list containing two lists of symbols.  Remember from earlier sections that the &lt;code&gt;car&lt;/code&gt; of a list is the first element in a list and the &lt;code&gt;cdr&lt;/code&gt; is the remainder of the list.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (cdr '((x1 x2) (y1 y2)))&lt;br /&gt;((y1 y2))&lt;/pre&gt;&lt;br /&gt;The fourth expression gets the second element of the same list as above.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (cadr '((x1 x2) (y1 y2)))&lt;br /&gt;(y1 y2)&lt;/pre&gt;&lt;br /&gt;The fifth expression is checking to see if the &lt;code&gt;car&lt;/code&gt; of a quoted list is a pair.  You should be able to see that it's not, but try evaluating sub-expressions if you're unsure.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; '(a short list)&lt;br /&gt;(a short list)&lt;br /&gt;&amp;gt; (car '(a short list))&lt;br /&gt;a&lt;br /&gt;&amp;gt; (pair? (car '(a short list)))&lt;br /&gt;#f&lt;/pre&gt;&lt;br /&gt;The sixth expression is using the &lt;code&gt;memq&lt;/code&gt; procedure to see if a symbol is contained in a list.  Remember that &lt;code&gt;memq&lt;/code&gt; only checks the highest-level elements of the list, it doesn't recursively look inside any sub-lists.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (memq 'red '((red shoes) (blue socks)))&lt;br /&gt;#f&lt;/pre&gt;&lt;br /&gt;The final expression is also using &lt;code&gt;memq&lt;/code&gt; to look for a symbol in a list, but this time with different results.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (memq 'red '(red shoes blue socks))&lt;br /&gt;(red shoes blue socks)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.54&lt;/span&gt; asks us to define a procedure &lt;code&gt;equal?&lt;/code&gt; that takes two parameters and returns true if they contain equal elements arranged in the same order.  The parameters can be values, symbols, lists of symbols, or lists containing both symbols and nested lists.  We are to define &lt;code&gt;equal?&lt;/code&gt; recursively in terms of the basic &lt;code&gt;eq?&lt;/code&gt; equality of symbols.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (equal? p1 p2)&lt;br /&gt;  (cond ((and (null? p1) (null? p2)) #t)&lt;br /&gt;        ((or (null? p1) (null? p2)) #f)&lt;br /&gt;        ((and (pair? p1) (pair? p2))&lt;br /&gt;         (and (equal? (car p1) (car p2))&lt;br /&gt;              (equal? (cdr p1) (cdr p2))))&lt;br /&gt;        ((or (pair? p1) (pair? p2)) #f)&lt;br /&gt;        (else (eq? p1 p2))))&lt;/pre&gt;&lt;br /&gt;The procedure starts by checking to see if both parameters are null and returns &lt;code&gt;#t&lt;/code&gt; if they are.  It then checks to see if only one parameter but not the other is null.  Next it checks to see if both parameters are pairs, and if they are it recursively checks to see if they have the same &lt;code&gt;car&lt;/code&gt; and the same &lt;code&gt;cdr&lt;/code&gt;.  Next it checks to see if only one of the parameters is a pair and returns &lt;code&gt;#f&lt;/code&gt; if that's the case.  Finally, it checks to see if the two parameters are the same symbol or have the same value.  We can run several tests to validate all the cases above.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;&amp;gt; (equal? '() '())&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (equal? '() 'a)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (equal? '((x1 x2) (y1 y2)) '((x1 x2) (y1 y2)))&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (equal? '((x1 x2) (y1 y2)) '((x1 x2 x3) (y1 y2)))&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (equal? '(x1 x2) 'y1)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (equal? 'abc 'abc)&lt;br /&gt;#t&lt;br /&gt;&amp;gt; (equal? 123 123)&lt;br /&gt;#t&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.55&lt;/span&gt; asks us to explain why when a user types the expression&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(car ''abracadabra)&lt;/pre&gt;&lt;br /&gt;the interpreter prints back &lt;code&gt;quote&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Remember that &lt;code&gt;'&lt;/code&gt; is just shorthand for &lt;code&gt;quote&lt;/code&gt;, so the expression above is equivalent to&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(car (quote (quote abracadabra)))&lt;/pre&gt;&lt;br /&gt;The sub-expression &lt;code&gt;(quote (quote abracadabra))&lt;/code&gt; is equivalent to &lt;code&gt;'(quote abracadabra)&lt;/code&gt;, which is just the list containing the two symbols &lt;code&gt;quote&lt;/code&gt; and &lt;code&gt;abracadabra&lt;/code&gt;, making the &lt;code&gt;car&lt;/code&gt; of that list simply the symbol &lt;code&gt;quote&lt;/code&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/6485935559345325496/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=6485935559345325496" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6485935559345325496?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/6485935559345325496?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/03/sicp-253-255-symbolic-data.html" title="SICP 2.53 - 2.55: Symbolic Data" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;Ck4BRHo_fip7ImA9WhRbFEU.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-645378151383003402</id><published>2012-02-05T17:08:00.005-05:00</published><updated>2012-02-05T17:29:15.446-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-05T17:29:15.446-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 2.52: Levels of Language for Robust Design</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4"&gt;2.2.4  Example: A Picture Language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Just as we did in previous exercises, we can use the &lt;a href="http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html"&gt;PLT Scheme SICP Picture Language&lt;/a&gt; package to run the solutions to the following exercises. You can load the picture package by putting the following &lt;code&gt;(require...)&lt;/code&gt; expression at the beginning of your Scheme file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Exercise 2.52&lt;/span&gt; asks us to make changes to the square limit of &lt;code&gt;wave&lt;/code&gt; shown in &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_fig_2.9"&gt;figure 2.9&lt;/a&gt; by working at the appropriate level of abstraction for the required change.  (We'll need all the code we wrote in exercises &lt;a href="http://www.billthelizard.com/2011/08/sicp-244-245-picture-language.html"&gt;2.44&lt;/a&gt; and &lt;a href="http://www.billthelizard.com/2011/10/sicp-249-defining-primitive-painters.html"&gt;2.49&lt;/a&gt; to start out with, so copy those into a new Scheme file.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2.52a.&lt;/span&gt;  Add some segments to the primitive &lt;code&gt;wave&lt;/code&gt; painter of exercise  2.49 (to add a smile, for example).&lt;br /&gt;&lt;br /&gt;This change requires that we make a change at a low level of abstraction, in adding segments to the &lt;code&gt;wave&lt;/code&gt; painter itself.  Let's add an eye and a smiling mouth on the left side of the head so it looks like the person in &lt;code&gt;wave&lt;/code&gt; is looking in that direction.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;; The wave painter (2.49d).&lt;br /&gt;; Add some segments to form a smile (2.52a)&lt;br /&gt;(define wave-segments&lt;br /&gt; (list&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.006 0.840)&lt;br /&gt;   (make-vect 0.155 0.591))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.006 0.635)&lt;br /&gt;   (make-vect 0.155 0.392))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.304 0.646)&lt;br /&gt;   (make-vect 0.155 0.591))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.298 0.591)&lt;br /&gt;   (make-vect 0.155 0.392))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.304 0.646)&lt;br /&gt;   (make-vect 0.403 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.298 0.591)&lt;br /&gt;   (make-vect 0.354 0.492))&lt;br /&gt;  (make-segment ; left face&lt;br /&gt;   (make-vect 0.403 0.646)&lt;br /&gt;   (make-vect 0.348 0.845))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.354 0.492)&lt;br /&gt;   (make-vect 0.249 0.000))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.403 0.000)&lt;br /&gt;   (make-vect 0.502 0.293))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.502 0.293)&lt;br /&gt;   (make-vect 0.602 0.000))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.348 0.845)&lt;br /&gt;   (make-vect 0.403 0.999))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.602 0.999)&lt;br /&gt;   (make-vect 0.652 0.845))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.652 0.845)&lt;br /&gt;   (make-vect 0.602 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.602 0.646)&lt;br /&gt;   (make-vect 0.751 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.751 0.646)&lt;br /&gt;   (make-vect 0.999 0.343))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.751 0.000)&lt;br /&gt;   (make-vect 0.597 0.442))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.597 0.442)&lt;br /&gt;   (make-vect 0.999 0.144))&lt;br /&gt;  (make-segment ; eye&lt;br /&gt;   (make-vect 0.395 0.916)&lt;br /&gt;   (make-vect 0.410 0.916))&lt;br /&gt;  (make-segment ; smile&lt;br /&gt;   (make-vect 0.376 0.746)&lt;br /&gt;   (make-vect 0.460 0.790))))&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 141px; height: 149px; border-style: none;" src="http://2.bp.blogspot.com/-qBg3kiF6cv4/Ty7_kbZo5pI/AAAAAAAAAfg/zg9uchIYyWk/s320/Smiling%2BWave.png" alt="" id="BLOGGER_PHOTO_ID_5705778779220666002" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;2.52b.&lt;/span&gt;  Change the pattern constructed by &lt;code&gt;corner-split&lt;/code&gt; (for example, by using only one copy of the &lt;code&gt;up-split&lt;/code&gt; and &lt;code&gt;right-split&lt;/code&gt; images instead of two).&lt;br /&gt;&lt;br /&gt;For this requirement we need to work in the middle layer of abstraction.  To use only one copy of the &lt;code&gt;up-split&lt;/code&gt; and &lt;code&gt;right-split&lt;/code&gt; images instead of two, we can simply remove the references to &lt;code&gt;top-left&lt;/code&gt; and &lt;code&gt;bottom-right&lt;/code&gt; that appear in the original implementation of &lt;code&gt;corner-split&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (corner-split painter n)&lt;br /&gt; (if (= n 0)&lt;br /&gt;     painter&lt;br /&gt;     (let ((up (up-split painter (- n 1)))&lt;br /&gt;           (right (right-split painter (- n 1)))&lt;br /&gt;           (corner (corner-split painter (- n 1))))&lt;br /&gt;         (beside (below painter up)&lt;br /&gt;                 (below right corner)))))&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 264px; height: 154px; border-style: none;" src="http://1.bp.blogspot.com/-lZtaone0zmk/Ty7_xwcNSkI/AAAAAAAAAfs/AKOsAi30LdM/s320/Corner-split%2Bwave.png" alt="" id="BLOGGER_PHOTO_ID_5705779008206883394" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2.52c.&lt;/span&gt;  Modify the version of &lt;code&gt;square-limit&lt;/code&gt; that uses &lt;code&gt;square-of-four&lt;/code&gt; so as to assemble the corners in a different pattern. (For example, you might make the big Mr. Rogers look outward from each corner of the square.)&lt;br /&gt;&lt;br /&gt;We're not using the Mr. Rogers painter from the text, but we can still rearrange the &lt;code&gt;square-limit&lt;/code&gt; painter so that the largest &lt;code&gt;wave&lt;/code&gt; image is drawn in the four corners by simply rotating the &lt;code&gt;corner-split&lt;/code&gt; painter by 180 degrees.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (square-limit painter n)&lt;br /&gt; (let ((quarter (rotate180 (corner-split painter n))))&lt;br /&gt;   (let ((half (beside (flip-horiz quarter) quarter)))&lt;br /&gt;     (below (flip-vert half) half))))&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 257px; height: 150px; border-style: none;" src="http://4.bp.blogspot.com/-J0o2yVFbunI/Ty7__dpeybI/AAAAAAAAAf4/Qigd1m5f02A/s320/Square-limit%2Bwave.png" alt="" id="BLOGGER_PHOTO_ID_5705779243680450994" border="0" /&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/645378151383003402/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=645378151383003402" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/645378151383003402?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/645378151383003402?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/02/sicp-252-levels-of-language-for-robust.html" title="SICP 2.52: Levels of Language for Robust Design" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-qBg3kiF6cv4/Ty7_kbZo5pI/AAAAAAAAAfg/zg9uchIYyWk/s72-c/Smiling%2BWave.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0YARnk-fip7ImA9WhRWFUk.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3393228170981432701</id><published>2012-01-02T17:28:00.008-05:00</published><updated>2012-01-02T17:59:07.756-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-02T17:59:07.756-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 2.50 - 2.51: Transforming and Combining Painters</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4"&gt;2.2.4  Example: A Picture Language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Just as we did in exercises &lt;a href="http://www.billthelizard.com/2011/08/sicp-244-245-picture-language.html"&gt;2.44, 2.45&lt;/a&gt;, and &lt;a href="http://www.billthelizard.com/2011/10/sicp-249-defining-primitive-painters.html"&gt;2.49&lt;/a&gt;, we can use the &lt;a href="http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html"&gt;PLT Scheme SICP Picture Language package&lt;/a&gt; to run the solutions to the following exercises. You can load the picture package by putting the following &lt;code&gt;(require...)&lt;/code&gt; expression at the beginning of your Scheme file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.50&lt;/span&gt;  asks us to define the transformation &lt;code&gt;flip-horiz&lt;/code&gt;, which flips painters horizontally, and transformations that rotate painters counterclockwise by 180 degrees and 270 degrees.&lt;br /&gt;&lt;br /&gt;We're expected to use the &lt;code&gt;transform-painter&lt;/code&gt; procedure defined earlier in section 2.2.4 of the text.  Since we're using the PLT Scheme SICP Picture Language package, we'll be using a version of &lt;code&gt;transform-painter&lt;/code&gt; that's defined slightly differently than the one in the text.  This procedure does not take the painter to be transformed as an argument, as does the version given in the text.  Instead it takes the points that specify the corners of the new frame as arguments and returns a procedure that takes the painter as its argument.&lt;br /&gt;&lt;br /&gt;For example, instead of defining &lt;code&gt;flip-vert&lt;/code&gt; as:&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (flip-vert painter)&lt;br /&gt;   (transform-painter painter&lt;br /&gt;             (make-vect 0.0 1.0)   ; new origin&lt;br /&gt;             (make-vect 1.0 1.0)   ; new end of edge1&lt;br /&gt;             (make-vect 0.0 0.0))) ; new end of edge2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We would instead pass the painter as an argument to the procedure returned from &lt;code&gt;transform-painter&lt;/code&gt; as follows:&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (flip-vertical painter)&lt;br /&gt;   ((transform-painter (make-vect 0.0 1.0)&lt;br /&gt;                       (make-vect 1.0 1.0)&lt;br /&gt;                       (make-vect 0.0 0.0))&lt;br /&gt;    painter))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The arguments to &lt;code&gt;transform-painter&lt;/code&gt; are points (represented as vectors) that specify the corners of the new frame.  The first point specifies the new frame's origin and the other two specify the ends of its edge vectors.  Remember that the origin point in a frame is normally in the lower left hand corner.  The first edge vector is the bottom edge of frame and the second edge vector is the left edge of the frame.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 197px; height: 174px; border-style: none;" src="http://3.bp.blogspot.com/-1BMv1duV79Q/TwIzOnAY3SI/AAAAAAAAAeM/5LVsDbUO0Gg/s320/Normal%2BFrame.png" alt="" id="BLOGGER_PHOTO_ID_5693169205031525666" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;These edges are defined by the points (0, 0) for the origin, (1, 0) for the end point of the first edge, and (0, 1) for the end point of the second edge.  In order to transform a painter we just need to redraw the figure above in the desired orientation, then call transform-painter with the new positions of the origin and the end points of the edges.&lt;br /&gt;&lt;br /&gt;To flip a painter horizontally we just move the origin and left edge to the right.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 197px; height: 174px; border-style: none;" src="http://1.bp.blogspot.com/-UrqMGNd1S6w/TwIzbkiuCxI/AAAAAAAAAeY/OxrDZks3XMk/s320/Flip%2BHorizontal%2BFrame.png" alt="" id="BLOGGER_PHOTO_ID_5693169427708513042" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;This gives the bottom edge a new endpoint as well.  The procedure (based on &lt;code&gt;flip-vert&lt;/code&gt;) would be:&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (flip-horizontal painter)&lt;br /&gt;   ((transform-painter (make-vect 1.0 0.0)   ; origin&lt;br /&gt;                       (make-vect 0.0 0.0)   ; corner1&lt;br /&gt;                       (make-vect 1.0 1.0))  ; corner2&lt;br /&gt;    painter))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The following images show the locations of the origin and edges when we rotate an image counterclockwise by 180 and 270 degrees.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 197px; height: 174px; border-style: none;" src="http://4.bp.blogspot.com/-hS2vR40mvhk/TwIznZyyO8I/AAAAAAAAAek/pZZlSiyJjOo/s320/Rotate%2B180%2BFrame.png" alt="" id="BLOGGER_PHOTO_ID_5693169630981536706" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 197px; height: 174px; border-style: none;" src="http://1.bp.blogspot.com/-9DIpNMxh-oA/TwIztyUBaCI/AAAAAAAAAew/mBXexvML0S4/s320/Rotate%2B270%2BFrame.png" alt="" id="BLOGGER_PHOTO_ID_5693169740642609186" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;We can implement the procedures using the origin and endpoints shown in the figures above.&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (rotate-180 painter)&lt;br /&gt;   ((transform-painter (make-vect 1.0 1.0)&lt;br /&gt;                       (make-vect 0.0 1.0)&lt;br /&gt;                       (make-vect 1.0 0.0))&lt;br /&gt;    painter))&lt;br /&gt;&lt;br /&gt;(define (rotate-270 painter)&lt;br /&gt;   ((transform-painter (make-vect 0.0 1.0)&lt;br /&gt;                       (make-vect 0.0 0.0)&lt;br /&gt;                       (make-vect 1.0 1.0))&lt;br /&gt;    painter))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Use the &lt;code&gt;einstein&lt;/code&gt; painter provided by the PLT Scheme SICP Picture Language package to check the output of the procedures above.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 213px; height: 320px; border-style: none;" src="http://3.bp.blogspot.com/-tv_PklWObok/TwI0MRshV1I/AAAAAAAAAe8/j3g58KBFfnE/s320/SICP%2BEx_2_50%2BOutput.png" alt="" id="BLOGGER_PHOTO_ID_5693170264462939986" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.51&lt;/span&gt; asks us to define the &lt;code&gt;below&lt;/code&gt; operation for painters. The &lt;code&gt;below&lt;/code&gt; procedure takes two painters as arguments. The resulting painter draws the first painter in the bottom of the frame and the second painter in the top. We're asked to define &lt;code&gt;below&lt;/code&gt; in two different ways -- first by writing a procedure that is analogous to the &lt;code&gt;beside&lt;/code&gt; procedure given in the text, and again in terms of &lt;code&gt;beside&lt;/code&gt; and suitable rotation operations like the ones we defined in exercise 2.50.&lt;br /&gt;&lt;br /&gt;Translating the &lt;code&gt;beside&lt;/code&gt; procedure from the text to create the first &lt;code&gt;below&lt;/code&gt; procedure is a simple matter of applying what we learned in exercise 2.50 above.&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;(define (beside painter1 painter2)&lt;br /&gt;   (let ((split-point (make-vect 0.5 0.0)))&lt;br /&gt;   (let ((paint-left&lt;br /&gt;         (transform-painter painter1&lt;br /&gt;                            (make-vect 0.0 0.0)&lt;br /&gt;                            split-point&lt;br /&gt;                            (make-vect 0.0 1.0)))&lt;br /&gt;         (paint-right&lt;br /&gt;         (transform-painter painter2&lt;br /&gt;                            split-point&lt;br /&gt;                           (make-vect 1.0 0.0)&lt;br /&gt;                           (make-vect 0.5 1.0))))&lt;br /&gt;   (lambda (frame)&lt;br /&gt;     (paint-left frame)&lt;br /&gt;     (paint-right frame)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;beside&lt;/code&gt; procedure first defines a &lt;code&gt;split-point&lt;/code&gt; at the bottom center of the frame that splits the frame vertically.  It then transforms the two painters provided so that they each fit into one half of the frame.  Finally, it returns a procedure that, when given a frame, paints the two images in the left and right halves of the frame.  Here's the analogous &lt;code&gt;below&lt;/code&gt; procedure:&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;; 2.51a&lt;br /&gt;(define (below-a painter1 painter2)&lt;br /&gt;   (let ((split-point (make-vect 0.0 0.5)))&lt;br /&gt;   (let ((paint-bottom&lt;br /&gt;        ((transform-painter (make-vect 0.0 0.0)&lt;br /&gt;                            (make-vect 1.0 0.0)&lt;br /&gt;                            split-point)&lt;br /&gt;         painter1))&lt;br /&gt;        (paint-top&lt;br /&gt;        ((transform-painter split-point&lt;br /&gt;                            (make-vect 1.0 0.5)&lt;br /&gt;                            (make-vect 0.0 1.0))&lt;br /&gt;         painter2)))&lt;br /&gt;   (lambda (frame)&lt;br /&gt;     (paint-bottom frame)&lt;br /&gt;     (paint-top frame)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We need to redefine the &lt;code&gt;split-point&lt;/code&gt; so that it divides the frame horizontally instead of vertically.  We then transform the painters so that they fit into the bottom and top halves of the frame.  Finally, we return a procedure that draws the two halves.&lt;br /&gt;&lt;br /&gt;The second implementation of &lt;code&gt;below&lt;/code&gt; is even simpler than the first.  We just need to draw the two painters beside each other then rotate the frame by 90 degrees.  When we do that the two images will be draw on their side, so we need to rotate the individual images 90 degrees in the opposite direction inside their smaller frames.  This is equivalent to rotating them 270 degrees in the same direction.&lt;br /&gt;&lt;pre class="prettyprint lang-lisp"&gt;; 2.51b&lt;br /&gt;(define (rotate-90 painter)&lt;br /&gt; ((transform-painter (make-vect 1.0 0.0)&lt;br /&gt;                     (make-vect 1.0 1.0)&lt;br /&gt;                     (make-vect 0.0 0.0))&lt;br /&gt;   painter))&lt;br /&gt;&lt;br /&gt;(define (below-b painter1 painter2)&lt;br /&gt;   (rotate-90 (beside (rotate-270 painter1) (rotate-270 painter2))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once again, we can test with &lt;code&gt;einstein&lt;/code&gt; to verify that these two procedures both give us the desired output.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 310px; height: 320px; border-style: none;" src="http://1.bp.blogspot.com/-NYpbFP5weN8/TwI0c71p3II/AAAAAAAAAfI/IkrgJWWYxUg/s320/SICP%2BEx_2_51%2BOutput.png" alt="" id="BLOGGER_PHOTO_ID_5693170550653443202" border="0" /&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3393228170981432701/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3393228170981432701" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3393228170981432701?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3393228170981432701?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2012/01/sicp-250-251-transforming-and-combining.html" title="SICP 2.50 - 2.51: Transforming and Combining Painters" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-1BMv1duV79Q/TwIzOnAY3SI/AAAAAAAAAeM/5LVsDbUO0Gg/s72-c/Normal%2BFrame.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;AkMDR3s8eip7ImA9WhRXFko.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-591430250251829465</id><published>2011-12-22T21:12:00.007-05:00</published><updated>2011-12-23T17:14:36.572-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-23T17:14:36.572-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzles" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>The "N Days of Christmas" Solution</title><content type="html">A few days ago in &lt;a href="http://www.billthelizard.com/2011/12/n-days-of-christmas-puzzle.html"&gt;The "N Days of Christmas" Puzzle&lt;/a&gt; I asked if you could figure out how many gifts you receive in total for all twelve days (not just on the twelfth day) of the song "The Twelve Days of Christmas," and to find an elegant way to calculate the number of gifts you'd receive if the number of days is extended beyond twelve.&lt;br /&gt;&lt;br /&gt;First we need to figure out how many gifts we receive on a given day.  It is a cumulative song, so you receive one partridge in a pear tree on the first day, then on the second day you receive two turtle doves and another partridge in a pear tree, and so on for twelve days.  So the sequence for each day is:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;1&lt;br /&gt;1 + 2 = 3&lt;br /&gt;1 + 2 + 3 = 6&lt;br /&gt;1 + 2 + 3 + 4 = 10&lt;br /&gt;1 + 2 + 3 + 4 + 5 = 15&lt;br /&gt;...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;That's probably enough terms that you'll start to recognize a pattern is forming.  Each number in the sequence is just the sum of the first n integers, which you may recognize as the &lt;a href="http://en.wikipedia.org/wiki/Triangular_number"&gt;triangle numbers&lt;/a&gt;.  For a small number of days like 12 we can just continue adding terms to the sequence and have the answer in about a minute.  We could look up the formula for the nth triangle number, but with a little bit of intuition we can come up with one ourselves.  (When you write your own blog, you get to pretend you're a little bit smarter and less lazy than you really are.)  Sometimes it helps to draw a picture like the following:&lt;br /&gt;&lt;br /&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 304px; height: 254px; border: none;" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SmqFILgNc5I/AAAAAAAAAI8/T2ctQVVVhvQ/s320/Sum+of+first+n+integers.png" alt="" id="BLOGGER_PHOTO_ID_5362244681911333778" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Notice that the circles form the same sequence that we're after.  Also note that since the circles are arranged in a triangle we can calculate the total number of circles by multiplying the height of the enclosing rectangle (n) by the width (n + 1) and dividing by 2.  This gives us the formula for the nth triangle number.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;$T_n = \frac{n(n + 1)}{2}$&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;That only gives us the number of gifts on the last day though.  We wanted to know the number of gifts on all days combined, and we wanted to know it for any number of days.  So what we really want isn't the nth triangle number (the sum of the first n integers), but the &lt;span style="font-style: italic;"&gt;sum of the first n triangle numbers&lt;/span&gt;.  That's a formula that we can derive from what we already know.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;$\sum_{k=1}^{n}\frac{k(k + 1)}{2}$&lt;br /&gt;&lt;br /&gt;$\frac{1}{2}\sum_{k=1}^{n}k(k + 1)$&lt;br /&gt;&lt;br /&gt;$\frac{1}{2}\sum_{k=1}^{n}(k^2 + k)$&lt;br /&gt;&lt;br /&gt;$\frac{1}{2}\sum_{k=1}^{n}k^2 + \frac{1}{2}\sum_{k=1}^{n}k$&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;At this point we should take a moment to say out loud what the two terms in this equation mean in plain English.  On the left we have one-half of the sum of the first n squares, and on the right we have one-half of the sum of the first n integers.  We already found a formula for the sum of the first n integers, and it seems like there ought to be a similar formula for the sum of the first n squares.  There is, and to save us some time I’ll just substitute it here&lt;sup&gt;1&lt;/sup&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;$\frac{1}{2}\frac{n (n + 1) (2n + 1)}{6} + \frac{1}{2}\frac{n (n + 1)}{2}$&lt;br /&gt;&lt;br /&gt;$\frac{(n^2 + n)(2n + 1)}{12} + \frac{n(n + 1)}{4}$&lt;br /&gt;&lt;br /&gt;$\frac{(2n^3 + 3n^2 + n)}{12} + \frac{(n^2 + n)}{4}$&lt;br /&gt;&lt;br /&gt;$\frac{(2n^3 + 3n^2 + n)}{12} + \frac{(3n^2 + 3n)}{12}$&lt;br /&gt;&lt;br /&gt;$\frac{(2n^3 + 6n^2 + 4n)}{12}$&lt;br /&gt;&lt;br /&gt;$\frac{(n^3 + 3n^2 + 2n)}{6}$&lt;br /&gt;&lt;br /&gt;$\frac{n(n^2 + 3n + 2)}{6}$&lt;br /&gt;&lt;br /&gt;$\frac{n(n + 1)(n + 2)}{6}$&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;That gives us our formula for the sum of the first n triangle numbers, which is also known as a &lt;a href="http://en.wikipedia.org/wiki/Tetrahedral_number"&gt;tetrahedral number&lt;/a&gt;.  This is the number you get when you turn the first n triangles on their side and stack them in a pyramid.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 200px; height: 230px; border: none;" src="http://4.bp.blogspot.com/-SmaxMNmoeTo/TvPkBgycdVI/AAAAAAAAAeA/eUJyDRbAPMs/s320/tetrahedral-number.jpg" alt="" id="BLOGGER_PHOTO_ID_5689141468931585362" border="0" /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So if we plug 12 into the formula above, we find out that in total there are&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;$\frac{12 \times 13 \times 14}{6} = 364$&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;total gifts given in the Twelve Days of Christmas.&lt;br /&gt;&lt;br /&gt;Happy Holidays!&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;sup&gt;1&lt;/sup&gt; The sequence given by the sum of the first N squares is called the  &lt;a href="http://en.wikipedia.org/wiki/Square_pyramidal_number"&gt;square pyramidal numbers&lt;/a&gt;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/591430250251829465/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=591430250251829465" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/591430250251829465?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/591430250251829465?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/12/n-days-of-christmas-solution.html" title="The &quot;N Days of Christmas&quot; Solution" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_PnLYRqe0k9g/SmqFILgNc5I/AAAAAAAAAI8/T2ctQVVVhvQ/s72-c/Sum+of+first+n+integers.png" height="72" width="72" /><thr:total>4</thr:total></entry><entry gd:etag="W/&quot;DUYFSXo8cSp7ImA9WhRXFk0.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-4830807528300454988</id><published>2011-12-16T22:58:00.006-05:00</published><updated>2011-12-22T21:25:18.479-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-22T21:25:18.479-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="puzzles" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>The "N Days of Christmas" Puzzle</title><content type="html">I received an interesting puzzle in an email from my friend Tim recently.  See if you can figure it out.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;My dad and I were bored at a Christmas concert lately, so we started&lt;br /&gt;talking about how many items you receive in the 12 days of Christmas.&lt;br /&gt;&lt;br /&gt;You get 1 item on day 1, 3 items on day 2, 6 on day 3, etc.  We&lt;br /&gt;figured that out pretty easily, but then we were trying to come up&lt;br /&gt;with a closed form solution for any number of days.&lt;br /&gt;&lt;br /&gt;When I got home and had some paper to work with I managed to do it,&lt;br /&gt;but I felt like my approach wasn't very nice.&lt;br /&gt;&lt;br /&gt;So, can you find a solution, and more importantly do you know an&lt;br /&gt;elegant way to do it?&lt;/blockquote&gt;&lt;br /&gt;If you're not familiar with the song, you can find the &lt;a href="http://en.wikipedia.org/wiki/12_days_of_Christmas#Structure"&gt;basic structure of the lyrics on Wikipedia&lt;/a&gt;, or just Google "the 12 days of Christmas" and you'll find it.&lt;br /&gt;&lt;br /&gt;Just to be clear, it is a &lt;span style="font-style: italic;"&gt;cumulative &lt;/span&gt;song, so you receive one partridge in a pear tree on the first day, then on the second day you receive two turtle doves and &lt;i&gt;another&lt;/i&gt; partridge in a pear tree, for a total of four items on the first two days, and so on for twelve days.  The puzzle is to find out how many gifts you receive in total for all twelve days (not just &lt;span style="font-style: italic;"&gt;on&lt;/span&gt; the twelfth day), and to find an elegant way to calculate the number of gifts you'd receive if the number of days is extended beyond twelve.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.billthelizard.com/2011/12/n-days-of-christmas-solution.html"&gt;You can see the solution here.&lt;/a&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/4830807528300454988/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=4830807528300454988" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4830807528300454988?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/4830807528300454988?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/12/n-days-of-christmas-puzzle.html" title="The &quot;N Days of Christmas&quot; Puzzle" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>9</thr:total></entry><entry gd:etag="W/&quot;C08AQX0_eyp7ImA9WhdbEUU.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-1530338215747511410</id><published>2011-10-09T13:09:00.006-04:00</published><updated>2011-10-09T13:37:20.343-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-09T13:37:20.343-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 2.49: Defining Primitive Painters</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4"&gt;2.2.4  Example: A Picture Language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.49&lt;/span&gt; asks us to use &lt;code&gt;segments-&amp;gt;painter&lt;/code&gt; to define the following primitive painters:&lt;br /&gt;&lt;br /&gt;&lt;ol style="list-style-type:lower-alpha;"&gt;&lt;li&gt;The painter that draws the outline of the designated frame.&lt;/li&gt;&lt;li&gt;The painter that draws an "X'' by connecting opposite corners of the frame.&lt;/li&gt;&lt;li&gt;The painter that draws a diamond shape by connecting the midpoints of the sides of the frame.&lt;/li&gt;&lt;li&gt;The wave painter. &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Just as we did in exercises &lt;a href="http://www.billthelizard.com/2011/08/sicp-244-245-picture-language.html"&gt;2.44 &amp;amp; 2.45&lt;/a&gt;, we can use the &lt;a href="http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html"&gt;PLT Scheme SICP Picture Language&lt;/a&gt; package to run the exercises. You can load the picture package by putting the following &lt;code&gt;(require...)&lt;/code&gt; expression at the beginning of your Scheme file.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Since &lt;code&gt;segments-&amp;gt;painter&lt;/code&gt; takes a list of segments as its input parameter, each solution is just a matter of figuring out the coordinates of the endpoints of each required segment.  Recall that the (0.0, 0.0) coordinate is the bottom left corner in the frame, not the top left corner as it is in many GUI environments.  For each solution, we can define the list of segments first, then define a painter.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.49 a.&lt;br /&gt;; The painter that draws the outline of the designated frame.&lt;br /&gt;(define outline-segments&lt;br /&gt; (list&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.0)&lt;br /&gt;   (make-vect 0.0 0.99))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.0)&lt;br /&gt;   (make-vect 0.99 0.0))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.99 0.0)&lt;br /&gt;   (make-vect 0.99 0.99))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.99)&lt;br /&gt;   (make-vect 0.99 0.99))))&lt;br /&gt;&lt;br /&gt;(define outline (segments-&amp;gt;painter outline-segments))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Note that I used 0.99 instead of 1.0 for the edges of the frame.   This is because the top and right edges won't be displayed if you use 1.0.&lt;br /&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 144px; height: 153px; border-style: none;" src="http://2.bp.blogspot.com/-2rA8vnjE7hk/TpHYMKu6ohI/AAAAAAAAAdI/WkvGQn60UTE/s320/Paint-Outline.png" alt="" id="BLOGGER_PHOTO_ID_5661543910132589074" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.49 b.&lt;br /&gt;; The painter that draws an ``X'' by connecting opposite corners of the frame.&lt;br /&gt;(define x-segments&lt;br /&gt; (list&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.0)&lt;br /&gt;   (make-vect 0.99 0.99))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.99)&lt;br /&gt;   (make-vect 0.99 0.0))))&lt;br /&gt;&lt;br /&gt;(define x-painter (segments-&amp;gt;painter x-segments))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 158px; height: 152px; border-style: none;" src="http://1.bp.blogspot.com/-w4fTfS1FCXc/TpHYdQYUaBI/AAAAAAAAAdQ/TClMRfQxi3s/s320/Paint-X.png" alt="" id="BLOGGER_PHOTO_ID_5661544203706198034" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.49 c.&lt;br /&gt;; The painter that draws a diamond shape by connecting the midpoints of the sides of the frame.&lt;br /&gt;(define diamond-segments&lt;br /&gt; (list&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.5)&lt;br /&gt;   (make-vect 0.5 0.0))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.0 0.5)&lt;br /&gt;   (make-vect 0.5 0.999))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.5 0.999)&lt;br /&gt;   (make-vect 0.999 0.5))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.999 0.5)&lt;br /&gt;   (make-vect 0.5 0.0))))&lt;br /&gt;&lt;br /&gt;(define diamond (segments-&amp;gt;painter diamond-segments))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 144px; height: 149px; border-style: none;" src="http://1.bp.blogspot.com/-E-Y2QbgPPBU/TpHYrXwADQI/AAAAAAAAAdY/pNm84HF3mME/s320/Paint-Diamond.png" alt="" id="BLOGGER_PHOTO_ID_5661544446202744066" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;wave&lt;/code&gt; painter in the last part of the exercise is the image shown in &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_Temp_203"&gt;Figure 2.10 of the text&lt;/a&gt;.  It consists of 17 separate segments.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.49 d.&lt;br /&gt;; The wave painter.&lt;br /&gt;(define wave-segments&lt;br /&gt; (list&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.006 0.840)&lt;br /&gt;   (make-vect 0.155 0.591))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.006 0.635)&lt;br /&gt;   (make-vect 0.155 0.392))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.304 0.646)&lt;br /&gt;   (make-vect 0.155 0.591))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.298 0.591)&lt;br /&gt;   (make-vect 0.155 0.392))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.304 0.646)&lt;br /&gt;   (make-vect 0.403 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.298 0.591)&lt;br /&gt;   (make-vect 0.354 0.492))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.403 0.646)&lt;br /&gt;   (make-vect 0.348 0.845))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.354 0.492)&lt;br /&gt;   (make-vect 0.249 0.000))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.403 0.000)&lt;br /&gt;   (make-vect 0.502 0.293))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.502 0.293)&lt;br /&gt;   (make-vect 0.602 0.000))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.348 0.845)&lt;br /&gt;   (make-vect 0.403 0.999))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.602 0.999)&lt;br /&gt;   (make-vect 0.652 0.845))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.652 0.845)&lt;br /&gt;   (make-vect 0.602 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.602 0.646)&lt;br /&gt;   (make-vect 0.751 0.646))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.751 0.646)&lt;br /&gt;   (make-vect 0.999 0.343))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.751 0.000)&lt;br /&gt;   (make-vect 0.597 0.442))&lt;br /&gt;  (make-segment&lt;br /&gt;   (make-vect 0.597 0.442)&lt;br /&gt;   (make-vect 0.999 0.144))))&lt;br /&gt;&lt;br /&gt;(define wave (segments-&amp;gt;painter wave-segments))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 143px; height: 148px; border-style: none;" src="http://2.bp.blogspot.com/-oZHLRV_LLzw/TpHY7UUZsGI/AAAAAAAAAdg/RywyFS13A0s/s320/Paint-Wave.png" alt="" id="BLOGGER_PHOTO_ID_5661544720159584354" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/1530338215747511410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=1530338215747511410" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1530338215747511410?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1530338215747511410?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/10/sicp-249-defining-primitive-painters.html" title="SICP 2.49: Defining Primitive Painters" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-2rA8vnjE7hk/TpHYMKu6ohI/AAAAAAAAAdI/WkvGQn60UTE/s72-c/Paint-Outline.png" height="72" width="72" /><thr:total>4</thr:total></entry><entry gd:etag="W/&quot;CEMMQXo7eyp7ImA9WhdVGUQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8379067155979543439</id><published>2011-09-25T18:56:00.002-04:00</published><updated>2011-09-25T19:14:40.403-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-25T19:14:40.403-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vectors" /><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 2.46 - 2.48: Frames &amp;  Painters</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4"&gt;2.2.4  Example: A Picture Language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A frame can be described by three vectors -- an origin vector and two edge vectors. The origin vector specifies the offset of the frame's origin from some absolute origin in the plane, and the edge vectors specify the offsets of the frame's corners from its origin. If the edges are perpendicular, the frame will be rectangular. Otherwise the frame will be a more general parallelogram.  A two-dimensional vector &lt;span style="font-style: italic;"&gt;v&lt;/span&gt; running from the origin to a point can be represented as a pair consisting of an x-coordinate and a y-coordinate.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.46&lt;/span&gt; asks us to implement a data abstraction for vectors by giving a constructor &lt;code&gt;make-vect&lt;/code&gt; and corresponding selectors &lt;code&gt;xcor-vect&lt;/code&gt; and &lt;code&gt;ycor-vect&lt;/code&gt;. In terms of these selectors and constructor, we'll also implement procedures &lt;code&gt;add-vect&lt;/code&gt;, &lt;code&gt;sub-vect&lt;/code&gt;, and &lt;code&gt;scale-vect&lt;/code&gt; that perform the operations for vector addition, vector subtraction, and multiplying a vector by a scalar:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;(x1, y1) + (x2, y2) = (x1 + x2, y1 + y2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(x1, y1) - (x2, y2) = (x1 - x2, y1 - y2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;s * (x, y) = (sx, sy)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The solution for the constructor and selectors uses &lt;code&gt;cons&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt;, and &lt;code&gt;cdr&lt;/code&gt; in the same pattern we've seen at least a dozen times by now.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (make-vect x y)&lt;br /&gt;   (cons x y))&lt;br /&gt;&lt;br /&gt;(define (xcor-vect v)&lt;br /&gt;   (car v))&lt;br /&gt;&lt;br /&gt;(define (ycor-vect v)&lt;br /&gt;   (cdr v))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Once we have those procedures in place, we can use them to build the vector operations specified.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (add-vect u v)&lt;br /&gt;   (make-vect&lt;br /&gt;     (+ (xcor-vect u) (xcor-vect v))&lt;br /&gt;     (+ (ycor-vect u) (ycor-vect v))))&lt;br /&gt;&lt;br /&gt;(define (sub-vect u v)&lt;br /&gt;   (make-vect&lt;br /&gt;     (- (xcor-vect u) (xcor-vect v))&lt;br /&gt;     (- (ycor-vect u) (ycor-vect v))))&lt;br /&gt;&lt;br /&gt;(define (scale-vect s v)&lt;br /&gt;   (make-vect&lt;br /&gt;     (* s (xcor-vect v))&lt;br /&gt;     (* s (ycor-vect v))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can test these procedures out with a few known values before moving on to the next step.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (define u (make-vect 2 4))&lt;br /&gt;&amp;gt; u&lt;br /&gt;(2 . 4)&lt;br /&gt;&amp;gt; (define v (make-vect 3 1))&lt;br /&gt;&amp;gt; v&lt;br /&gt;(3 . 1)&lt;br /&gt;&amp;gt; (define w (add-vect u v))&lt;br /&gt;&amp;gt; w&lt;br /&gt;(5 . 5)&lt;br /&gt;&amp;gt; (define x (sub-vect w u))&lt;br /&gt;&amp;gt; x&lt;br /&gt;(3 . 1)&lt;br /&gt;&amp;gt; (define y (scale-vect 3 w))&lt;br /&gt;&amp;gt; y&lt;br /&gt;(15 . 15)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.47&lt;/span&gt; gives us the following constructors for frames, one using list and the other using cons:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (make-frame origin edge1 edge2)&lt;br /&gt;   (list origin edge1 edge2))&lt;br /&gt;&lt;br /&gt;(define (make-frame origin edge1 edge2)&lt;br /&gt;   (cons origin (cons edge1 edge2)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're asked to supply the appropriate selectors to produce an implementation for frames for each of the two constructors.  Like any selector implementation, the task here is simply to extract each piece from the assembled object.  We'll follow the naming convention from the previous exercise and call our selectors &lt;code&gt;origin-frame&lt;/code&gt;, &lt;code&gt;edge1-frame&lt;/code&gt;, and &lt;code&gt;edge2-frame&lt;/code&gt;.  Let's start with the version that uses &lt;code&gt;list&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.47a&lt;br /&gt;(define (make-frame origin edge1 edge2)&lt;br /&gt;   (list origin edge1 edge2))&lt;br /&gt;&lt;br /&gt;(define (origin-frame frame)&lt;br /&gt;   (car frame))&lt;br /&gt;&lt;br /&gt;(define (edge1-frame frame)&lt;br /&gt;   (car (cdr frame)))&lt;br /&gt;&lt;br /&gt;(define (edge2-frame frame)&lt;br /&gt;   (car (cdr (cdr frame))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The selectors simply use the right combinations of &lt;code&gt;car&lt;/code&gt; and &lt;code&gt;cdr&lt;/code&gt; to extract the appropriate elements from the list.  We can test it with some of the same values used in the previous exercise, but we'll need to add an origin vector.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (define f (make-frame (make-vect 0 0) (make-vect 2 4) (make-vect 3 1)))&lt;br /&gt;&amp;gt; f&lt;br /&gt;((0 . 0) (2 . 4) (3 . 1))&lt;br /&gt;&amp;gt; (origin-frame f)&lt;br /&gt;(0 . 0)&lt;br /&gt;&amp;gt; (edge1-frame f)&lt;br /&gt;(2 . 4)&lt;br /&gt;&amp;gt; (edge2-frame f)&lt;br /&gt;(3 . 1)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Because the internal representation of a frame is different in the second implementation of &lt;code&gt;make-frame&lt;/code&gt;, one of the selectors will have to change for the second part of the exercise.  The original &lt;code&gt;origin-frame&lt;/code&gt; and &lt;code&gt;edge1-frame&lt;/code&gt; implementations will still work, but the &lt;code&gt;edge2-frame&lt;/code&gt; procedure causes an error if you try to use it.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;; 2.47b&lt;br /&gt;(define (make-frame origin edge1 edge2)&lt;br /&gt;   (cons origin (cons edge1 edge2)))&lt;br /&gt;&lt;br /&gt;(define (edge2-frame frame)&lt;br /&gt;   (cdr (cdr frame)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Run exactly the same test from above to verify that you get the same results (except for the internal structure of the frame in the second step).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (define f (make-frame (make-vect 0 0) (make-vect 2 4) (make-vect 3 1)))&lt;br /&gt;&amp;gt; f&lt;br /&gt;((0 . 0) (2 . 4) 3 . 1)&lt;br /&gt;&amp;gt; (origin-frame f)&lt;br /&gt;(0 . 0)&lt;br /&gt;&amp;gt; (edge1-frame f)&lt;br /&gt;(2 . 4)&lt;br /&gt;&amp;gt; (edge2-frame f)&lt;br /&gt;(3 . 1)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.48&lt;/span&gt; asks us to define a representation for segments using our vector representation from exercise 2.46 above.  We'll need to define the constructor &lt;code&gt;make-segment&lt;/code&gt; and the selectors &lt;code&gt;start-segment&lt;/code&gt; and &lt;code&gt;end-segment&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (make-segment v1 v2)&lt;br /&gt;   (cons v1 v2))&lt;br /&gt;&lt;br /&gt;(define (start-segment segment)&lt;br /&gt;   (car segment))&lt;br /&gt;&lt;br /&gt;(define (end-segment segment)&lt;br /&gt;   (cdr segment))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Again, these use the same pattern we've seen before.  In the next exercise, we'll take a closer look at the procedures above by drawing pictures with line segments using &lt;a href="http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html"&gt;The SICP Picture Language&lt;/a&gt; package.&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8379067155979543439/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8379067155979543439" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8379067155979543439?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8379067155979543439?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/09/sicp-246-248-frames-painters.html" title="SICP 2.46 - 2.48: Frames &amp;  Painters" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>6</thr:total></entry><entry gd:etag="W/&quot;DkcBRHg5eip7ImA9WhdQGEo.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8639701219743757264</id><published>2011-08-20T16:00:00.018-04:00</published><updated>2011-08-20T17:00:55.622-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-20T17:00:55.622-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 2.44 &amp; 2.45: A Picture Language</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.4"&gt;2.2.4  Example: A Picture Language&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;The next section of SICP is an extended example that illustrates the features of the picture language introduced in &lt;a href="http://www.billthelizard.com/2011/07/sicp-lecture-3a-henderson-escher.html"&gt;SICP Lecture 3A: Henderson Escher Example&lt;/a&gt;.  I'm going to be using the &lt;a href="http://planet.plt-scheme.org/package-source/soegaard/sicp.plt/2/1/planet-docs/sicp-manual/index.html"&gt;PLT Scheme SICP Picture Language package&lt;/a&gt; to run the examples and exercises.  You can load the picture package by putting the following &lt;code&gt;(require...)&lt;/code&gt; expression at the beginning of your Scheme file.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(require (planet "sicp.ss" ("soegaard" "sicp.plt" 2 1)))
&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;The &lt;code&gt;painter&lt;/code&gt; primitive in the PLT package behaves slightly differently than the one presented in the text, in that it doesn't display itself.  To display a &lt;code&gt;painter&lt;/code&gt; you must call the &lt;code&gt;paint&lt;/code&gt; procedure, which takes a &lt;code&gt;painter&lt;/code&gt; as its argument.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (paint einstein)&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://1.bp.blogspot.com/-6-jet2OGFv0/TlAT9ESi_1I/AAAAAAAAAbY/Z26TwrFaFWw/s320/Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643032272939712338" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint diagonal-shading)&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 133px; height: 132px; border-style: none;" src="http://2.bp.blogspot.com/-44Ipr1gKTQo/TlAUEwQsCiI/AAAAAAAAAbg/auAieKWnvns/s320/Diagonal-Shading.png" alt="" id="BLOGGER_PHOTO_ID_5643032405002160674" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;The &lt;code&gt;einstein&lt;/code&gt; and &lt;code&gt;diagonal-shading&lt;/code&gt; painter values are built in to the PLT Scheme Picture Language package.  The package also includes procedures for flipping, rotating and combining painter values, similar to those discussed in the lecture.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (paint (flip-horiz einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://2.bp.blogspot.com/-pmgtk6T9VVc/TlAUMEt_yLI/AAAAAAAAAbo/1zKbCPEgJ88/s320/Flip-Horiz-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643032530752882866" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint (flip-vert einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 131px; border-style: none;" src="http://3.bp.blogspot.com/-Wvy8wHSMsno/TlAUS4U1UDI/AAAAAAAAAbw/3Y4wC-VCXl0/s320/Flip-Vert-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643032647685197874" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint (rotate90 einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 131px; height: 132px; border-style: none;" src="http://3.bp.blogspot.com/-d_gs20QbFgI/TlAUat2eePI/AAAAAAAAAb4/fNZU0c6MJdQ/s320/Rotate90-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643032782312470770" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint (beside einstein einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 131px; border-style: none;" src="http://1.bp.blogspot.com/-T1ElQKSPLWM/TlAUlFuiUNI/AAAAAAAAAcA/AmU4QaVMp88/s320/Beside-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643032960520310994" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint (below einstein einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://1.bp.blogspot.com/-5rtslaW3kgQ/TlAUrRRhWLI/AAAAAAAAAcI/Jtw1eR-ovrY/s320/Below-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643033066699053234" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;Now that we can work with painters, we can start to combine them in ways that form patterns.  For example, the text shows us how we can combine an image beside a flipped representation of itself, then draw the resulting painter below itself.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (flipped-pairs painter)
&lt;br /&gt;   (let ((painter2 (beside painter (flip-vert painter))))
&lt;br /&gt;     (below painter2 painter2)))
&lt;br /&gt;
&lt;br /&gt;&amp;gt; (paint (flipped-pairs einstein))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 131px; border-style: none;" src="http://4.bp.blogspot.com/-TYlQWP58KCA/TlAUzItluhI/AAAAAAAAAcQ/gAmIO-qkNds/s320/Flipped-Pairs-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643033201839815186" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;We can also define recursive operations, like &lt;code&gt;right-split&lt;/code&gt;, which makes painters split and branch towards the right as many times as we specify.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (right-split painter n)
&lt;br /&gt;   (if (= n 0)
&lt;br /&gt;       painter
&lt;br /&gt;       (let ((smaller (right-split painter (- n 1))))
&lt;br /&gt;         (beside painter (below smaller smaller)))))
&lt;br /&gt;
&lt;br /&gt;&amp;gt; (paint (right-split einstein 3))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://1.bp.blogspot.com/-6UWV0czFmJo/TlAU78Z7WlI/AAAAAAAAAcY/CHeFLNLubWM/s320/Right-Split-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643033353154943570" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.44&lt;/span&gt; asks us to define the procedure &lt;code&gt;up-split&lt;/code&gt;.  It's similar to &lt;code&gt;right-split&lt;/code&gt;, except that it switches the roles of &lt;code&gt;below&lt;/code&gt; and &lt;code&gt;beside&lt;/code&gt;.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (up-split painter n)
&lt;br /&gt;   (if (= n 0)
&lt;br /&gt;       painter
&lt;br /&gt;       (let ((smaller (up-split painter (- n 1))))
&lt;br /&gt;         (below painter (beside smaller smaller)))))
&lt;br /&gt;
&lt;br /&gt;&amp;gt; (paint (up-split einstein 3))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 131px; border-style: none;" src="http://4.bp.blogspot.com/-2q3vAbTiw8A/TlAVGTFQNAI/AAAAAAAAAcg/FL5Aw-qkgcI/s320/Up-Split-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643033531040936962" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;Once we have both &lt;code&gt;right-split&lt;/code&gt; and &lt;code&gt;up-split&lt;/code&gt; defined, we can create balanced patterns by branching in both directions.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (corner-split painter n)
&lt;br /&gt;   (if (= n 0)
&lt;br /&gt;      painter
&lt;br /&gt;       (let ((up (up-split painter (- n 1)))
&lt;br /&gt;            (right (right-split painter (- n 1))))
&lt;br /&gt;         (let ((top-left (beside up up))
&lt;br /&gt;               (bottom-right (below right right))
&lt;br /&gt;               (corner (corner-split painter (- n 1))))
&lt;br /&gt;           (beside (below painter top-left)
&lt;br /&gt;                   (below bottom-right corner))))))
&lt;br /&gt;
&lt;br /&gt;&amp;gt; (paint (corner-split einstein 1))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://4.bp.blogspot.com/-x83nqG2hTcI/TlAVOM-ts_I/AAAAAAAAAco/D3jxpZwhuac/s320/Corner-Split-Einstein-1.png" alt="" id="BLOGGER_PHOTO_ID_5643033666841850866" border="0" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;&amp;gt; (paint (corner-split einstein 2))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 132px; height: 132px; border-style: none;" src="http://4.bp.blogspot.com/-7R6gTwcHXjE/TlAVVG0hFZI/AAAAAAAAAcw/DfrzzomFsjg/s320/Corner-Split-Einstein-2.png" alt="" id="BLOGGER_PHOTO_ID_5643033785447552402" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;By combining four copies of the &lt;code&gt;corner-split&lt;/code&gt; pattern, we can create the &lt;code&gt;square-limit&lt;/code&gt; pattern from the Escher drawing that we saw in the lecture.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (square-limit painter n)
&lt;br /&gt;   (let ((quarter (corner-split painter n)))
&lt;br /&gt;     (let ((half (beside (flip-horiz quarter) quarter)))
&lt;br /&gt;       (below (flip-vert half) half))))
&lt;br /&gt;
&lt;br /&gt;&amp;gt; (paint (square-limit einstein 4))&lt;/code&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 131px; height: 131px; border-style: none;" src="http://2.bp.blogspot.com/-wYnk1LpJgf0/TlAVblg1XOI/AAAAAAAAAc4/G4Z9ykQz3Ew/s320/Square-Limit-Einstein.png" alt="" id="BLOGGER_PHOTO_ID_5643033896765709538" border="0" /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.45&lt;/span&gt; points out that &lt;code&gt;right-split&lt;/code&gt; and &lt;code&gt;up-split&lt;/code&gt; can be expressed as instances of a general splitting operation.  We are to define a &lt;code&gt;split&lt;/code&gt; procedure, and then rewrite &lt;code&gt;right-split&lt;/code&gt; and &lt;code&gt;up-split&lt;/code&gt; in terms of &lt;code&gt;split&lt;/code&gt; as follows:
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define right-split (split beside below))
&lt;br /&gt;(define up-split (split below beside))
&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;We already noted the similarity between the two procedures &lt;code&gt;right-split&lt;/code&gt; and &lt;code&gt;up-split&lt;/code&gt; when we solved exercise 2.44 above.  The only real difference between them is in which direction they split the painter first.  Given the amount of duplication between the two, we can use either one of these procedures as a template for &lt;code&gt;split&lt;/code&gt;.
&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 11px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (split dir1 dir2)
&lt;br /&gt;   (lambda (painter n)
&lt;br /&gt;     (if (= n 0)
&lt;br /&gt;         painter
&lt;br /&gt;         (let ((smaller ((split dir1 dir2) painter (- n 1))))
&lt;br /&gt;           (dir1 painter (dir2 smaller smaller))))))
&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;The biggest change is that &lt;code&gt;split&lt;/code&gt; uses a lambda to return the procedure that it creates.  Once you're done substituting the new definitions for &lt;code&gt;right-split&lt;/code&gt; and &lt;code&gt;up-split&lt;/code&gt;, you can run the &lt;code&gt;square-limit&lt;/code&gt; procedure again to verify that the output hasn't changed.
&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;br /&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8639701219743757264/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8639701219743757264" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8639701219743757264?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8639701219743757264?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/08/sicp-244-245-picture-language.html" title="SICP 2.44 &amp; 2.45: A Picture Language" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-6-jet2OGFv0/TlAT9ESi_1I/AAAAAAAAAbY/Z26TwrFaFWw/s72-c/Einstein.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0AHRnw-eyp7ImA9WhdSFU4.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8402167415847541285</id><published>2011-07-24T16:02:00.008-04:00</published><updated>2011-07-24T16:35:37.253-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-24T16:35:37.253-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="learning" /><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 Lecture 3A: Henderson Escher Example</title><content type="html">Structure and Interpretation of Computer Programs&lt;br /&gt;Henderson Escher Example&lt;br /&gt;Covers Text &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.2"&gt;Section 2.2.2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/"&gt;download the video lecture&lt;/a&gt; or stream it on &lt;a href="http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/"&gt;MIT's OpenCourseWare site&lt;/a&gt;. It's also available on &lt;a href="http://www.youtube.com/v/2QgZVYI3tDs"&gt;YouTube&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This lecture is presented by &lt;a href="http://groups.csail.mit.edu/mac/users/hal/hal.html"&gt;Professor Harold Abelson&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This lecture starts out with a review of the material covered in the &lt;a href="http://www.billthelizard.com/2010/09/sicp-lecture-2b-compound-data.html"&gt;previous lecture on compound data&lt;/a&gt;.  The main points covered are pairs and the closure property (the things we make by forming pairs can also be combined to form pairs).&lt;br /&gt;&lt;br /&gt;We're then shown how cons can be used to create lists of primitive elements in Scheme.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(cons 1&lt;br /&gt;    (cons 2&lt;br /&gt;         (cons 3&lt;br /&gt;              (cons 4 nil))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;is the same as&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(list 1 2 3 4)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;A common pattern in programming is to write procedures that takes a list, do something to every element of that list, and return a list containing the results.  We saw an example, scale-list, that takes a list and a factor and returns the result of each element in the list multiplied by the factor.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (scale-list items factor)&lt;br /&gt;   (if (null? items)&lt;br /&gt;       nil&lt;br /&gt;       (cons (* (car items) factor)&lt;br /&gt;             (scale-list (cdr items) factor))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In Scheme terms, the general pattern here is to recursively do something to the cdr of the list and cons that on to actually doing something to the first element of the list.&lt;br /&gt;&lt;blockquote&gt;The very fact that there's a general pattern there means I shouldn't be writing this procedure at all.&lt;/blockquote&gt;&lt;br /&gt;Instead of embedding a general pattern in each procedure that uses it, we should write a procedure that's the general pattern itself and write our procedure in terms of that higher-order procedure.  For this example, that higher-order procedure is map.  (See &lt;a href="http://www.billthelizard.com/2011/01/sicp-221-223-mapping-over-lists.html"&gt;SICP 2.21 - 2.23: Mapping over lists&lt;/a&gt; for examples.)&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (map proc items)&lt;br /&gt;   (if (null? items)&lt;br /&gt;       nil&lt;br /&gt;       (cons (proc (car items))&lt;br /&gt;             (map proc (cdr items)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The important idea here is that we stop thinking about control structures and start thinking about applying operations to aggregates.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Henderson Escher Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The remainder of the lecture talks about one particular example, the Henderson Escher Example, that summarizes everything that's been covered in the course so far, list structure, abstraction, representation, and capturing commonality with higher-order procedures.  It also goes into the third major theme of the course, meta-linguistic abstraction.&lt;br /&gt;&lt;br /&gt;Meta-linguistic abstraction:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Primitives&lt;/li&gt;&lt;li&gt;Means of Combination&lt;/li&gt;&lt;li&gt;Means of Abstraction&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The example is a language developed by Peter Henderson for describing images that are composed of repeated elements that are shifted and scaled, like the M. C. Escher woodcut "Square Limit" pictured below.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.wikipaintings.org/en/m-c-escher/square-limit-colour"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 318px;" src="http://2.bp.blogspot.com/-MFwDsU2b6Co/Tix71lLJQcI/AAAAAAAAAa4/HdWqLBFgrIw/s320/square-limit-colour.jpg" alt="" id="BLOGGER_PHOTO_ID_5633013394375786946" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The other theme illustrated by this example is the issue that there is no real difference between procedures and data.&lt;br /&gt;&lt;br /&gt;The language operates on primitives called pictures.  A picture is a procedure that draws a figure scaled to fit a rectangle that you specify.  The following operations are supported in the language.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;rotate - Rotate a picture 90 degrees.&lt;/li&gt;&lt;li&gt;flip - Flip a picture horizonally or vertically.&lt;/li&gt;&lt;li&gt;beside - Draw two pictures beside one another.&lt;/li&gt;&lt;li&gt;above - Draw two pictures, one above the other.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The closure property allows you to build complex pictures with just these few operations and one primitive (the picture itself).  When you combine two pictures with beside or above, the result is itself a picture, which can be combined with other pictures.&lt;br /&gt;&lt;br /&gt;We're going to see a lot of details concerning the implementation of the picture language illustrated in this example as we go through the exercises in the next section of the text, so I won't reproduce those details here.  The gist is that we define one set of procedures to &lt;span style="font-style: italic;"&gt;draw pictures inside of rectangles&lt;/span&gt;, another set of procedures that &lt;span style="font-style: italic;"&gt;do the geometric manipulations of those pictures&lt;/span&gt; listed above (rotate, flip, beside, and above), then a higher-order set of procedures that &lt;span style="font-style: italic;"&gt;combine those manipulated pictures in different ways&lt;/span&gt; to make an image like the Escher drawing above..&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Software Design Methodologies&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The last part of the lecture talks about the common software design methodology of decomposing a problem into discrete components, which are themselves decomposed into discrete components, and so on until you reach a design that looks like the tree structure below.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-Ge6va5xpZfY/Tix8Mu4hCEI/AAAAAAAAAbA/ebghCwqthzg/s1600/TreeExpansion.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 141px;" src="http://2.bp.blogspot.com/-Ge6va5xpZfY/Tix8Mu4hCEI/AAAAAAAAAbA/ebghCwqthzg/s320/TreeExpansion.png" alt="" id="BLOGGER_PHOTO_ID_5633013792118999106" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Each component in this kind of design is created to do one specific task, and the components only communicate with direct parent or child components in the hierarchy.  Contrast this with the way the picture language was developed in the Henderson Escher example.  First, a language for drawing primitive pictures was presented, then on top of that we build a language for geometric rotations, and finally, on top of that we built a language for schemes of combination.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-qzc1XP8qDG8/Tix8Y08bQ5I/AAAAAAAAAbI/7qU0I_FxWv8/s1600/Language%2BLayers.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 200px;" src="http://1.bp.blogspot.com/-qzc1XP8qDG8/Tix8Y08bQ5I/AAAAAAAAAbI/7qU0I_FxWv8/s320/Language%2BLayers.png" alt="" id="BLOGGER_PHOTO_ID_5633013999904441234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This scheme gives you a full range of linguistic power at each level.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Lisp is a lousy language for doing any particular problem.  What it's good for is figuring out the right language that you want and embedding that in Lisp.&lt;/blockquote&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8402167415847541285/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8402167415847541285" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8402167415847541285?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8402167415847541285?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/07/sicp-lecture-3a-henderson-escher.html" title="SICP Lecture 3A: Henderson Escher Example" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-MFwDsU2b6Co/Tix71lLJQcI/AAAAAAAAAa4/HdWqLBFgrIw/s72-c/square-limit-colour.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkINQX4-fCp7ImA9WhdTEk4.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8077965154892559717</id><published>2011-07-09T12:41:00.006-04:00</published><updated>2011-07-09T12:56:30.054-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-09T12:56:30.054-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="letter frequency" /><category scheme="http://www.blogger.com/atom/ns#" term="data visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="qwerty" /><category scheme="http://www.blogger.com/atom/ns#" term="dvorak" /><title>Letter Frequencies and Keyboard Layouts</title><content type="html">I saw Mike Knuepfel's &lt;a href="http://itp.nyu.edu/%7Emk3321/itp_blog/?p=779"&gt;Keyboard Frequency Sculpture&lt;/a&gt; a few weeks ago and thought it was an excellent idea for visualizing letter frequency data.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-M4fPXoExrvQ/ThiE-YDo47I/AAAAAAAAAaY/zYWFmAO6UaA/s1600/keyboard-sculpture.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 218px;" src="http://4.bp.blogspot.com/-M4fPXoExrvQ/ThiE-YDo47I/AAAAAAAAAaY/zYWFmAO6UaA/s320/keyboard-sculpture.jpg" alt="" id="BLOGGER_PHOTO_ID_5627393941543904178" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The height of each key corresponds to how frequently that letter is used in samples of English writing.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-bu9bvCIyenY/ThiHXRaqC5I/AAAAAAAAAaw/Ye8T11ZuqSY/s1600/letter-frequency.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://2.bp.blogspot.com/-bu9bvCIyenY/ThiHXRaqC5I/AAAAAAAAAaw/Ye8T11ZuqSY/s320/letter-frequency.png" alt="" id="BLOGGER_PHOTO_ID_5627396568281385874" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I wanted to see how the layout of the most frequently used letters on a &lt;a href="http://en.wikipedia.org/wiki/QWERTY"&gt;QWERTY&lt;/a&gt; keyboard compared to those on a &lt;a href="http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard"&gt;Dvorak&lt;/a&gt; keyboard.  Unfortunately, I'm no sculptor, and I couldn't see an easy way to slice and edit the original image to rearrange the keys, so I decided to use a color mapping instead.&lt;br /&gt;&lt;br /&gt;The images below were created using the same &lt;a href="http://en.wikipedia.org/wiki/Letter_frequency"&gt;letter frequency&lt;/a&gt; chart as the original sculpture.  Pure &lt;span style="color: rgb(0, 0, 255); font-weight: bold;"&gt;blue&lt;/span&gt; is for the least frequently used letters, while pure &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;red&lt;/span&gt; is most frequent.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MW2-mIV1sX8/ThiFkgVJHLI/AAAAAAAAAag/dbX8SteEmsc/s1600/Color%2BQwerty%2BKeyboard.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 109px;" src="http://2.bp.blogspot.com/-MW2-mIV1sX8/ThiFkgVJHLI/AAAAAAAAAag/dbX8SteEmsc/s320/Color%2BQwerty%2BKeyboard.png" alt="" id="BLOGGER_PHOTO_ID_5627394596599831730" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt;QWERTY&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-0GerAGiQ4vk/ThiFwdLf5kI/AAAAAAAAAao/CnMK2sDvdHk/s1600/Color%2BDvorak%2BKeyboard.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 109px;" src="http://3.bp.blogspot.com/-0GerAGiQ4vk/ThiFwdLf5kI/AAAAAAAAAao/CnMK2sDvdHk/s320/Color%2BDvorak%2BKeyboard.png" alt="" id="BLOGGER_PHOTO_ID_5627394801912505922" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt;Dvorak&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Note that the majority of the most frequently used keys are on the home row in the Dvorak layout, but they're scattered all around on a QWERTY keyboard.  The QWERTY layout originated in the very early days of mechanical typewriters, so the keys were arranged such that common two-letter combinations were placed on opposite sides of the keyboard so that the mechanical parts would not jam.  The Dvorak layout was designed to reduce finger motion in order to increase typing rate and decrease errors.  Despite these advantages, the Dvorak layout has still failed to catch on.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8077965154892559717/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8077965154892559717" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8077965154892559717?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8077965154892559717?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/07/letter-frequencies-and-keyboard-layouts.html" title="Letter Frequencies and Keyboard Layouts" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-M4fPXoExrvQ/ThiE-YDo47I/AAAAAAAAAaY/zYWFmAO6UaA/s72-c/keyboard-sculpture.jpg" height="72" width="72" /><thr:total>20</thr:total></entry><entry gd:etag="W/&quot;DkEAQn85fip7ImA9WhZaFEo.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3516816270565878717</id><published>2011-06-30T18:23:00.005-04:00</published><updated>2011-06-30T18:57:23.126-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-30T18:57:23.126-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sequences" /><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="chess" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>SICP 2.42 &amp; 2.43: The N Queens Problem</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Eight_queens_puzzle"&gt;eight queens puzzle&lt;/a&gt; is the problem of placing eight queens on an 8x8 chess board so that no two queens attack each other.  A solution requires that no two queens share the same row, column, or diagonal.  One possible solution (there are 92) is shown in the figure below.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-78viBhysECo/Tgz4jXLHmhI/AAAAAAAAAZA/AfYCbSr03bw/s1600/Eight%2BQueens%2BSolution.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 288px; height: 288px;" src="http://3.bp.blogspot.com/-78viBhysECo/Tgz4jXLHmhI/AAAAAAAAAZA/AfYCbSr03bw/s320/Eight%2BQueens%2BSolution.png" alt="" id="BLOGGER_PHOTO_ID_5624143321078667794" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The eight queens puzzle is an example of the more general &lt;span style="font-style: italic;"&gt;n queens problem&lt;/span&gt; of placing n queens on an nxn chessboard.  SICP suggests that one way to solve the puzzle is to work across the board, placing a queen in each column.  Once k - 1 queens are placed, the kth queen must be placed in a position where it is not in check from any of the queens already on the board.  This approach can be formulated recursively.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Assume that we have already generated the sequence of all possible ways to place k - 1 queens in the first k - 1 columns of the board. For each of these ways, generate an extended set of positions by placing a queen in each row of the kth column. Now filter these, keeping only the positions for which the queen in the kth column is safe with respect to the other queens. This produces the sequence of all ways to place k queens in the first k columns. By continuing this process, we will produce not only one solution, but all solutions to the puzzle.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.42&lt;/span&gt; implements a partial solution as the procedure &lt;code&gt;queens&lt;/code&gt;, which returns a sequence of all solutions to the problem of placing n queens on an nxn board.  The internal procedure &lt;code&gt;queen-cols&lt;/code&gt; returns the sequence of all ways to place queens in the first k columns of the board.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (queens board-size)&lt;br /&gt;   (define (queen-cols k) &lt;br /&gt;     (if (= k 0)&lt;br /&gt;         (list empty-board)&lt;br /&gt;         (filter&lt;br /&gt;          (lambda (positions) (safe? k positions))&lt;br /&gt;          (flatmap&lt;br /&gt;           (lambda (rest-of-queens)&lt;br /&gt;             (map (lambda (new-row)&lt;br /&gt;                    (adjoin-position new-row k rest-of-queens))&lt;br /&gt;                  (enumerate-interval 1 board-size)))&lt;br /&gt;           (queen-cols (- k 1))))))&lt;br /&gt;   (queen-cols board-size))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In this procedure &lt;code&gt;rest-of-queens&lt;/code&gt; is a way to place k - 1 queens in the first k - 1 columns, and the parameter &lt;code&gt;new-row&lt;/code&gt; is a proposed row in which to place the queen for the kth column.&lt;br /&gt;&lt;br /&gt;Our task is to complete the program by implementing the representation for sets of board positions, including the procedure &lt;code&gt;adjoin-position&lt;/code&gt;, which adjoins a new row-column position to a set of positions, and &lt;code&gt;empty-board&lt;/code&gt;, which represents an empty set of positions.  (Note that the word &lt;span style="font-style:italic;"&gt;position&lt;/span&gt; in this problem means the row and column of a single queen, not the placement of all pieces on the board, as is the normal use of the word position in chess terminology.  Here the plural form &lt;span style="font-style:italic;"&gt;positions&lt;/span&gt; is used to indicate the position of all the queens on a single board.  A set of positions represents one solution to the problem.)  We must also write the procedure &lt;code&gt;safe?&lt;/code&gt;, which determines for a set of positions, whether the queen in the kth column is safe with respect to the others.&lt;br /&gt;&lt;br /&gt;Since a position is just a row-column pair, we can use what should by now be the familiar method for representing pairs.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (make-position row col)&lt;br /&gt;   (cons row col))&lt;br /&gt;&lt;br /&gt;(define (position-row position)&lt;br /&gt;   (car position))&lt;br /&gt;&lt;br /&gt;(define (position-col position)&lt;br /&gt;   (cdr position))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can represent an empty board with &lt;code&gt;null&lt;/code&gt;, and adjoin a new position to a board using list operations.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define empty-board null)&lt;br /&gt;&lt;br /&gt;(define (adjoin-position row col positions)&lt;br /&gt;   (append positions (list (make-position row col))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;A queen is safe if no other queen is in the same row, column, or diagonal.  Since we're only placing one queen in each column at a time, we can skip checking the column.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (safe? col positions)&lt;br /&gt;   (let ((kth-queen (list-ref positions (- col 1)))&lt;br /&gt;         (other-queens (filter (lambda (q)&lt;br /&gt;                                 (not (= col (position-col q))))&lt;br /&gt;                               positions)))&lt;br /&gt;   (define (attacks? q1 q2)&lt;br /&gt;     (or (= (position-row q1) (position-row q2))&lt;br /&gt;         (= (abs (- (position-row q1) (position-row q2)))&lt;br /&gt;            (abs (- (position-col q1) (position-col q2))))))&lt;br /&gt;&lt;br /&gt;   (define (iter q board)&lt;br /&gt;     (or (null? board)&lt;br /&gt;         (and (not (attacks? q (car board)))&lt;br /&gt;              (iter q (cdr board)))))&lt;br /&gt;   (iter kth-queen other-queens)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;safe?&lt;/code&gt; procedure starts be defining the symbols &lt;code&gt;kth-queen&lt;/code&gt; and &lt;code&gt;other-queens&lt;/code&gt;.  We use the &lt;code&gt;list-ref&lt;/code&gt; procedure introduced in &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.1"&gt;SICP section 2.2.1&lt;/a&gt; to separate the kth queen from the rest of the board.  Next we define an &lt;code&gt;attacks?&lt;/code&gt; procedure that takes two queens and returns true if they are in the same row or on the same diagonal.  Then we define an iterative helper procedure to check and see if the kth queen attacks any of the others.&lt;br /&gt;&lt;br /&gt;After adding in the definitions for &lt;code&gt;accumulate&lt;/code&gt;, &lt;code&gt;flatmap&lt;/code&gt;, and &lt;code&gt;enumerate-interval&lt;/code&gt; given earlier in the text, we can finally test our implementation of &lt;code&gt;queens&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (queens 1)&lt;br /&gt;(((1 . 1)))&lt;br /&gt;&amp;gt; (queens 2)&lt;br /&gt;()&lt;br /&gt;&amp;gt; (queens 3)&lt;br /&gt;()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So far, so good.  There is only one solution to the puzzle for a 1x1 board, and no possible solutions for 2x2 and 3x3 boards.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (queens 4)&lt;br /&gt;(((2 . 1) (4 . 2) (1 . 3) (3 . 4)) ((3 . 1) (1 . 2) (4 . 3) (2 . 4)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The two solutions given for a 4x4 board are illustrated below.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-yeIDQWPY6nw/Tgz40RKbzHI/AAAAAAAAAZI/I8mlSTVDgSk/s1600/4%2BQueens%2BSolution%2B1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 144px; height: 144px;" src="http://3.bp.blogspot.com/-yeIDQWPY6nw/Tgz40RKbzHI/AAAAAAAAAZI/I8mlSTVDgSk/s320/4%2BQueens%2BSolution%2B1.png" alt="" id="BLOGGER_PHOTO_ID_5624143611522960498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-L-6KOy70QHg/Tgz46kIk_kI/AAAAAAAAAZQ/66EgYh5zOIo/s1600/4%2BQueens%2BSolution%2B2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 144px; height: 144px;" src="http://1.bp.blogspot.com/-L-6KOy70QHg/Tgz46kIk_kI/AAAAAAAAAZQ/66EgYh5zOIo/s320/4%2BQueens%2BSolution%2B2.png" alt="" id="BLOGGER_PHOTO_ID_5624143719694663234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;For the remaining tests, we'll just show how many distinct solutions &lt;code&gt;queens&lt;/code&gt; comes up with instead of listing them all.  You can check that the number of solutions matches those given in the &lt;a href="http://oeis.org/A000170"&gt;Online Encyclopedia of Integer Sequences A000170&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (length (queens 5))&lt;br /&gt;10&lt;br /&gt;&amp;gt; (length (queens 6))&lt;br /&gt;4&lt;br /&gt;&amp;gt; (length (queens 7))&lt;br /&gt;40&lt;br /&gt;&amp;gt; (length (queens 8))&lt;br /&gt;92&lt;br /&gt;&amp;gt; (length (queens 9))&lt;br /&gt;352&lt;br /&gt;&amp;gt; (length (queens 10))&lt;br /&gt;724&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.43&lt;/span&gt; gives the following alternate implementation for a portion of the &lt;code&gt;queens&lt;/code&gt; procedure above.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(flatmap&lt;br /&gt;  (lambda (new-row)&lt;br /&gt;    (map (lambda (rest-of-queens)&lt;br /&gt;           (adjoin-position new-row k rest-of-queens))&lt;br /&gt;         (queen-cols (- k 1))))&lt;br /&gt;  (enumerate-interval 1 board-size))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This new implementation works, but it runs extremely slowly because the order of nested mappings in &lt;code&gt;flatmap&lt;/code&gt; has been swapped.  Our task is to explain why this interchange makes the program run slowly, and to estimate how long it will take the new implementation to solve the eight queens puzzle assuming that the original implementation solved the puzzle in time T.&lt;br /&gt;&lt;br /&gt;In the original solution, &lt;code&gt;queen-cols&lt;/code&gt; is called once for each column in the board.  This is an expensive procedure to call, since it generates the sequence of all possible ways to place k queens in k columns.  By moving &lt;code&gt;queen-cols&lt;/code&gt; so it gets called by &lt;code&gt;flatmap&lt;/code&gt;, we're transforming a linear recursive process to a tree-recursive process.  The &lt;code&gt;flatmap&lt;/code&gt; procedure is called for each row of the kth column, so the new procedure is generating &lt;span style="font-style:italic;"&gt;all the possible solutions&lt;/span&gt; for the first k - 1 columns for each one of these rows.&lt;br /&gt;&lt;br /&gt;We learned back 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; that a tree-recursive process grows exponentially.  If it takes time T to execute the original version of &lt;code&gt;queens&lt;/code&gt; for a given board size, we can expect the new version to take roughly T&lt;sup&gt;board-size&lt;/sup&gt; time to execute.&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3516816270565878717/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3516816270565878717" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3516816270565878717?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3516816270565878717?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/06/sicp-242-243-n-queens-problem.html" title="SICP 2.42 &amp; 2.43: The N Queens Problem" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-78viBhysECo/Tgz4jXLHmhI/AAAAAAAAAZA/AfYCbSr03bw/s72-c/Eight%2BQueens%2BSolution.png" height="72" width="72" /><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;A0YCQ3o8eSp7ImA9WhZVF0s.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8444991394489698182</id><published>2011-05-30T11:01:00.002-04:00</published><updated>2011-05-30T11:26:02.471-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-30T11:26:02.471-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sequences" /><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 2.40 &amp; 2.41: Nested Mappings</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The next sub-section of SICP shows us how we can express nested loops using sequence operations.  The first example given is the following problem:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Given a positive integer n, find all ordered pairs of distinct positive integers i and j, where 1 &amp;lt;= j &amp;lt; i &amp;lt;= n, such that (i + j) is prime.&lt;/blockquote&gt;&lt;br /&gt;In pseudocode, a solution using nested loops would be:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;for i = 1 to n:&lt;br /&gt;   for j = 1 to (i - 1):&lt;br /&gt;       if isPrime( i + j ):&lt;br /&gt;           print i, j, i + j&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For n = 6, the output of the program above would be:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;2, 1, 3&lt;br /&gt;3, 2, 5&lt;br /&gt;4, 1, 5&lt;br /&gt;4, 3, 7&lt;br /&gt;5, 2, 7&lt;br /&gt;6, 1, 7&lt;br /&gt;6, 5, 11&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;One way of looking at this is that the two nested loops generate a sequence of pairs, and the if statement applies a filter to each pair in the sequence.&lt;br /&gt;&lt;br /&gt;In Scheme we can produce a sequence of pairs using nested mappings.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(accumulate append&lt;br /&gt;           null&lt;br /&gt;           (map (lambda (i)&lt;br /&gt;                  (map (lambda (j) (list i j))&lt;br /&gt;                       (enumerate-interval 1 (- i 1))))&lt;br /&gt;                (enumerate-interval 1 n)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;flatmap&lt;/code&gt; procedure is defined to abstract the portion of the code above that accumulates with &lt;code&gt;append&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (flatmap proc seq)&lt;br /&gt;   (accumulate append null (map proc seq)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Procedures are then defined to filter out prime sums and to create the pair sum output from each pair in the sequence.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (prime-sum? pair)&lt;br /&gt;   (prime? (+ (car pair) (cadr pair))))&lt;br /&gt;&lt;br /&gt;(define (make-pair-sum pair)&lt;br /&gt;   (list (car pair) (cadr pair) (+ (car pair) (cadr pair))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Combining all of these steps with the &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;enumerate-interval&lt;/code&gt; procedures from earlier in SICP section 2.2.3, we get the complete procedure.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (prime-sum-pairs n)&lt;br /&gt;   (map make-pair-sum&lt;br /&gt;        (filter prime-sum?&lt;br /&gt;                (flatmap&lt;br /&gt;                 (lambda (i)&lt;br /&gt;                   (map (lambda (j) (list i j))&lt;br /&gt;                        (enumerate-interval 1 (- i 1))))&lt;br /&gt;                 (enumerate-interval 1 n)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.40&lt;/span&gt; asks us to define a procedure &lt;code&gt;unique-pairs&lt;/code&gt; that, given an integer n, generates the sequence of pairs &lt;code&gt;(i j)&lt;/code&gt; with 1 &amp;lt;= j &amp;lt; i &amp;lt;= n.  We are to use &lt;code&gt;unique-pairs&lt;/code&gt; to simplify the definition of &lt;code&gt;prime-sum-pairs&lt;/code&gt; given above.&lt;br /&gt;&lt;br /&gt;Since we already have code embedded in &lt;code&gt;prime-sum-pairs&lt;/code&gt; that generates the sequence of unique pairs that we need, this exercise basically amounts to an &lt;a href="http://www.refactoring.com/catalog/extractMethod.html"&gt;extract method&lt;/a&gt; refactoring of that piece of code.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (unique-pairs n)&lt;br /&gt;   (flatmap&lt;br /&gt;    (lambda (i)&lt;br /&gt;      (map (lambda (j) (list i j))&lt;br /&gt;           (enumerate-interval 1 (- i 1))))&lt;br /&gt;    (enumerate-interval 1 n)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The body of &lt;code&gt;unique-pairs&lt;/code&gt; is a simple copy/paste from &lt;code&gt;prime-sum-pairs&lt;/code&gt;.  Replacing that portion of code in the original is just as easy.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (prime-sum-pairs n)&lt;br /&gt;   (map make-pair-sum&lt;br /&gt;        (filter prime-sum?&lt;br /&gt;                (unique-pairs n))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can test it with a known value to verify.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;gt; (prime-sum-pairs 6)&lt;br /&gt;((2 1 3) (3 2 5) (4 1 5) (4 3 7) (5 2 7) (6 1 7) (6 5 11))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.41&lt;/span&gt; asks us to write a procedure to find all ordered triples of distinct positive integers i, j, and k less than or equal to a given integer n that sum to a given integer s.&lt;br /&gt;&lt;br /&gt;If we were solving this using loops, we'd just nest our loops three deep.  This exercise teaches us that nested mappings can be extended the same way.  Let's start by creating a procedure that just finds ordered triples of distinct positive integers.  We'll base it on &lt;code&gt;unique-pairs&lt;/code&gt; from the previous exercise.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (ordered-triples n)&lt;br /&gt;   (flatmap (lambda (i)&lt;br /&gt;      (flatmap (lambda (j)&lt;br /&gt;         (map (lambda (k)&lt;br /&gt;                (list i j k))&lt;br /&gt;              (enumerate-interval 1 (- j 1))))&lt;br /&gt;       (enumerate-interval 1 (- i 1))))&lt;br /&gt;    (enumerate-interval 1 n)))&lt;br /&gt;&lt;br /&gt;&amp;gt; (ordered-triples 5)&lt;br /&gt;((3 2 1)&lt;br /&gt;(4 2 1)&lt;br /&gt;(4 3 1)&lt;br /&gt;(4 3 2)&lt;br /&gt;(5 2 1)&lt;br /&gt;(5 3 1)&lt;br /&gt;(5 3 2)&lt;br /&gt;(5 4 1)&lt;br /&gt;(5 4 2)&lt;br /&gt;(5 4 3))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Next we can create a filtering procedure that checks to see if a triple sums to a given integer.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (triple-sum? triple s)&lt;br /&gt;   (= s (accumulate + 0 triple)))&lt;br /&gt;&lt;br /&gt;&amp;gt; (triple-sum? (list 1 2 3) 5)&lt;br /&gt;#f&lt;br /&gt;&amp;gt; (triple-sum? (list 1 2 3) 6)&lt;br /&gt;#t&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We also need a procedure to append the sum of the elements of a triple to the end of the triple so it's included in the output.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (make-triple-sum triple)&lt;br /&gt;   (append triple (list (accumulate + 0 triple))))&lt;br /&gt;&lt;br /&gt;&amp;gt; (make-triple-sum (list 1 2 3))&lt;br /&gt;(1 2 3 6)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Finally, we can put it all together.  Since &lt;code&gt;filter&lt;/code&gt; takes only two arguments, a predicate and a sequence, we need to embed our predicate procedure &lt;code&gt;triple-sum?&lt;/code&gt; in the final solution so that it can have access to the target sum variable s.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;(define (ordered-triple-sum n s)&lt;br /&gt;   (define (triple-sum? triple)&lt;br /&gt;     (= s (accumulate + 0 triple)))&lt;br /&gt;   (map make-triple-sum&lt;br /&gt;        (filter triple-sum?&lt;br /&gt;                (ordered-triples n))))&lt;br /&gt;&lt;br /&gt;&amp;gt; (ordered-triple-sum 5 10)&lt;br /&gt;((5 3 2 10) (5 4 1 10))&lt;br /&gt;&amp;gt; (ordered-triple-sum 10 5)&lt;br /&gt;()&lt;br /&gt;&amp;gt; (ordered-triple-sum 10 6)&lt;br /&gt;((3 2 1 6))&lt;br /&gt;&amp;gt; (ordered-triple-sum 12 12)&lt;br /&gt;((5 4 3 12)&lt;br /&gt;(6 4 2 12)&lt;br /&gt;(6 5 1 12)&lt;br /&gt;(7 3 2 12)&lt;br /&gt;(7 4 1 12)&lt;br /&gt;(8 3 1 12)&lt;br /&gt;(9 2 1 12))&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8444991394489698182/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8444991394489698182" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8444991394489698182?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8444991394489698182?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/05/sicp-240-241-nested-mappings.html" title="SICP 2.40 &amp; 2.41: Nested Mappings" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>4</thr:total></entry><entry gd:etag="W/&quot;DEQARHo8fSp7ImA9WhZXEUQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-1167328195436710680</id><published>2011-04-30T16:29:00.004-04:00</published><updated>2011-04-30T16:45:45.475-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-30T16:45:45.475-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="sequences" /><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 2.38 &amp; 2.39: Folding Left and Right</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.38&lt;/span&gt; informs us that another name for the &lt;code&gt;accumulate&lt;/code&gt; procedure we've been using is &lt;code&gt;fold-right&lt;/code&gt;, because it combines the elements of a sequence starting on the left and moving to the right.  There's also a fold-left procedure that combines elements working in the opposite direction.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;; fold-right is another name for accumulate&lt;br /&gt;(define (fold-right op initial sequence)&lt;br /&gt;   (if (null? sequence)&lt;br /&gt;       initial&lt;br /&gt;       (op (car sequence)&lt;br /&gt;           (fold-right op initial (cdr sequence)))))&lt;br /&gt;&lt;br /&gt;; fold-left is given in exercise 2.38&lt;br /&gt;(define (fold-left op initial sequence)&lt;br /&gt;   (define (iter result rest)&lt;br /&gt;     (if (null? rest)&lt;br /&gt;         result&lt;br /&gt;         (iter (op result (car rest))&lt;br /&gt;               (cdr rest))))&lt;br /&gt;   (iter initial sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're given a few expressions that illustrate how these two procedures behave differently.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (fold-right / 1 (list 1 2 3))&lt;br /&gt;1 1/2&lt;br /&gt;&amp;gt; (fold-left / 1 (list 1 2 3))&lt;br /&gt;1/6&lt;br /&gt;&amp;gt; (fold-right list null (list 1 2 3))&lt;br /&gt;(1 (2 (3 ())))&lt;br /&gt;&amp;gt; (fold-left list null (list 1 2 3))&lt;br /&gt;(((() 1) 2) 3)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We're asked what property the &lt;code&gt;op&lt;/code&gt; parameter needs to satisfy to guarantee that &lt;code&gt;fold-right&lt;/code&gt; and &lt;code&gt;fold-left&lt;/code&gt; will produce the same values for any sequence.&lt;br /&gt;&lt;br /&gt;The property that will guarantee that &lt;code&gt;fold-right&lt;/code&gt; and &lt;code&gt;fold-left&lt;/code&gt; will produce the same values for any sequence is &lt;a href="http://en.wikipedia.org/wiki/Commutativity"&gt;commutativity&lt;/a&gt;.  You may remember the commutative property of both addition and multiplication from algebra.  It's the law that says that:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;A + B = B + A&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;and&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;A x B = B x A&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Subtraction and division are &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; commutative operations.  The AND and OR operations in &lt;a href="http://en.wikipedia.org/wiki/Boolean_algebra_%28logic%29"&gt;Boolean algebra&lt;/a&gt; are commutative.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.39&lt;/span&gt; asks us to complete the following definitions of &lt;code&gt;reverse&lt;/code&gt; (&lt;a href="http://www.billthelizard.com/2010/12/sicp-218-reversing-list.html"&gt;from exercise 2.18&lt;/a&gt;) in terms of &lt;code&gt;fold-right&lt;/code&gt; and &lt;code&gt;fold-left&lt;/code&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (reverse sequence)&lt;br /&gt;   (fold-right (lambda (x y) &amp;lt;??&amp;gt;) null sequence))&lt;br /&gt;&lt;br /&gt;(define (reverse sequence)&lt;br /&gt;   (fold-left (lambda (x y) &amp;lt;??&amp;gt;) null sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Since we only need to define the operator used in each implementation, the key to this exercise lies in how the operator is applied in each folding procedure.  Pay close attention to the order of the arguments of the &lt;code&gt;op&lt;/code&gt; procedure.&lt;br /&gt;&lt;br /&gt;In &lt;code&gt;fold-right&lt;/code&gt; the operator is applied to the &lt;code&gt;car&lt;/code&gt; of the sequence and the result of a recursive call to &lt;code&gt;fold-right&lt;/code&gt;.  Just as we did in exercise 2.18, we can reverse the sequence using &lt;code&gt;fold-right&lt;/code&gt; by appending the &lt;code&gt;car&lt;/code&gt; of the sequence to the reverse of its &lt;code&gt;cdr&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (reverse sequence)&lt;br /&gt;   (fold-right (lambda (x y) (append y (list x))) null sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In &lt;code&gt;fold-left&lt;/code&gt; the operator is applied to the result sequence and the &lt;code&gt;car&lt;/code&gt; of the unused elements in the initial sequence.  Since the result sequence starts with an initial value of &lt;code&gt;null&lt;/code&gt;, and we're starting at the end of the sequence and working backwards anyway, we can just &lt;code&gt;cons&lt;/code&gt; each element to the end of the result.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (reverse sequence)&lt;br /&gt;   (fold-left (lambda (x y) (cons y x)) null sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As expected, we get the same test results for either of the two &lt;code&gt;reverse&lt;/code&gt; implementations above.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (reverse (list 1 2 3 4))&lt;br /&gt;(4 3 2 1)&lt;br /&gt;&amp;gt; (reverse (list 1 4 9 16 25))&lt;br /&gt;(25 16 9 4 1)&lt;br /&gt;&amp;gt; (reverse (list 1 3 5 7))&lt;br /&gt;(7 5 3 1)&lt;br /&gt;&amp;gt; (reverse (list 23 72 149 34))&lt;br /&gt;(34 149 72 23)&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/1167328195436710680/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=1167328195436710680" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1167328195436710680?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/1167328195436710680?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/04/sicp-238-239-folding-left-and-right.html" title="SICP 2.38 &amp; 2.39: Folding Left and Right" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>7</thr:total></entry><entry gd:etag="W/&quot;DkYGQ34_cSp7ImA9WhZQFkQ.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-7006144058667705953</id><published>2011-04-24T14:56:00.006-04:00</published><updated>2011-04-24T21:15:22.049-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-24T21:15:22.049-04: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" /><category scheme="http://www.blogger.com/atom/ns#" term="matrix" /><title>SICP 2.36 &amp; 2.37: Matrix Algebra</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.36&lt;/span&gt; asks us to complete the &lt;code&gt;accumulate-n&lt;/code&gt; procedure, which is similar to &lt;code&gt;accumulate&lt;/code&gt; except that it takes as its third argument a sequence of sequences that are assumed to all have the same length.  It applies the accumulation procedure to all the first elements of the sub-sequences, all the second elements, third elements, and so on and returns a sequence of the results.  For example, given the sequence s containing the following values, &lt;code&gt;((1 2 3) (4 5 6) (7 8 9) (10 11 12))&lt;/code&gt;, the value of &lt;code&gt;(accumulate-n + 0 s)&lt;/code&gt; should return the sequence &lt;code&gt;(22 26 30)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Our task is to fill in the missing expressions in the following definition:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (accumulate-n op init seqs)&lt;br /&gt;   (if (null? (car seqs))&lt;br /&gt;       null&lt;br /&gt;       (cons (accumulate op init &amp;lt;??&amp;gt;)&lt;br /&gt;             (accumulate-n op init &amp;lt;??&amp;gt;))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If you've been doing all the exercises up to this point, then this procedure's overall structure of recursively building up a sequence with &lt;code&gt;cons&lt;/code&gt; will be familiar.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.billthelizard.com/2011/04/sicp-235-counting-leaves-of-tree.html"&gt;exercise 2.35&lt;/a&gt; we used &lt;code&gt;map&lt;/code&gt; and a simple lambda expression to flatten out a tree so the result could be used as the third parameter to &lt;code&gt;accumulate&lt;/code&gt;.  We can do something very similar here to fill in the missing expressions above.  We'll still use &lt;code&gt;map&lt;/code&gt; to loop over each of the sub-sequences, but in this case we need &lt;code&gt;map&lt;/code&gt; to return a sequence that contains the first element from each sub-sequence (in the first missing expression) and the remaining elements of each sub-sequence (in the second missing expression).  We already know two procedures that meet those needs, &lt;code&gt;car&lt;/code&gt; and &lt;code&gt;cdr&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;; accumulate from sicp section 2.2.3&lt;br /&gt;(define (accumulate op initial sequence)&lt;br /&gt;   (if (null? sequence)&lt;br /&gt;       initial&lt;br /&gt;       (op (car sequence)&lt;br /&gt;           (accumulate op initial (cdr sequence)))))&lt;br /&gt;&lt;br /&gt;(define (accumulate-n op init seqs)&lt;br /&gt;   (if (null? (car seqs))&lt;br /&gt;       null&lt;br /&gt;       (cons (accumulate op init (map car seqs))&lt;br /&gt;             (accumulate-n op init (map cdr seqs)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The first call to &lt;code&gt;map&lt;/code&gt; returns a sequence containing the first element of each of the original sub-sequences.  The second call to &lt;code&gt;map&lt;/code&gt; returns the sequence of sub-sequences with each of their first elements removed.    This continues recursively until no more elements remain.  We can test the solution with the values given in the exercise.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (define s (list (list 1 2 3) (list 4 5 6) (list 7 8 9) (list 10 11 12)))&lt;br /&gt;&amp;gt; s&lt;br /&gt;((1 2 3) (4 5 6) (7 8 9) (10 11 12))&lt;br /&gt;&amp;gt; (accumulate-n + 0 s)&lt;br /&gt;(22 26 30)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.37&lt;/span&gt; introduces a representation for vectors and matrices.  A vector can be represented as a sequence of numbers, and a &lt;a href="http://mathworld.wolfram.com/Matrix.html"&gt;matrix&lt;/a&gt; as a sequence of vectors.  For example, the matrix&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-7HQe_3yyrIY/TbR6UArPpWI/AAAAAAAAAYs/nK9U8Wnj_uo/s1600/matrix.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 142px; height: 86px;" src="http://2.bp.blogspot.com/-7HQe_3yyrIY/TbR6UArPpWI/AAAAAAAAAYs/nK9U8Wnj_uo/s320/matrix.png" alt="" id="BLOGGER_PHOTO_ID_5599234720925721954" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;can be represented as the sequence &lt;code&gt;((1 2 3 4) (4 5 6 6) (6 7 8 9))&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;We can use this representation to express the basic operations of matrix algebra in terms of sequence operations.  These basic operations are:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(dot-product v w)&lt;/code&gt; - returns the sum Σ&lt;sub&gt;i&lt;/sub&gt;(v&lt;sub&gt;i&lt;/sub&gt;w&lt;sub&gt;i&lt;/sub&gt;)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(matrix-*-vector m v)&lt;/code&gt; - returns the vector t, where t&lt;sub&gt;i&lt;/sub&gt; = Σ&lt;sub&gt;j&lt;/sub&gt;(m&lt;sub&gt;ij&lt;/sub&gt;v&lt;sub&gt;j&lt;/sub&gt;)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(matrix-*-matrix m n)&lt;/code&gt; - returns the matrix p, where p&lt;sub&gt;ij&lt;/sub&gt; = Σ&lt;sub&gt;k&lt;/sub&gt;(m&lt;sub&gt;ik&lt;/sub&gt;n&lt;sub&gt;kj&lt;/sub&gt;)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(transpose mat)&lt;/code&gt; - returns the matrix n, where n&lt;sub&gt;ij&lt;/sub&gt; = m&lt;sub&gt;ji&lt;/sub&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dot product&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Dot_product"&gt;dot product&lt;/a&gt; is defined for us.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (dot-product v w)&lt;br /&gt;   (accumulate + 0 (map * v w)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;dot-product&lt;/code&gt; procedure takes two vectors (that are assumed to be equal length) and returns a single number obtained by multiplying corresponding elements and then summing those products.&lt;br /&gt;&lt;br /&gt;Note that the use of &lt;code&gt;map&lt;/code&gt; in this procedure takes more arguments than we've seen up to this point.  That's because &lt;code&gt;map&lt;/code&gt; takes a procedure of &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; arguments, together with &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; lists, and applies the procedure to all the first elements of the lists, all the second elements of the lists, and so on, returning a list of the results.  Up to this point, we've been using &lt;code&gt;map&lt;/code&gt; where &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; = 1.&lt;br /&gt;&lt;br /&gt;Our task is to fill in the missing expressions in the given procedures for computing the remaining matrix operations.  Let's take them one at a time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Multiply a matrix by a vector&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (matrix-*-vector m v)&lt;br /&gt;   (map &amp;lt;??&amp;gt; m))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When &lt;a href="http://www.facstaff.bucknell.edu/mastascu/elessonsHTML/Circuit/MatVecMultiply.htm"&gt;multiplying a matrix by a vector&lt;/a&gt;, each row of the matrix is multiplied by the vector (using the dot product procedure described above).  The result is a vector containing each dot product.  Since &lt;code&gt;map&lt;/code&gt; will pass each row of the matrix to whatever function we provide, we can just define a lambda expression that uses the &lt;code&gt;dot-product&lt;/code&gt; procedure already defined.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (matrix-*-vector m v)&lt;br /&gt;   (map (lambda (row) (dot-product row v)) m))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Transpose a matrix&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (transpose mat)&lt;br /&gt;   (accumulate-n &amp;lt;??&amp;gt; &amp;lt;??&amp;gt; mat))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;There are several ways of looking at &lt;a href="http://en.wikipedia.org/wiki/Transpose"&gt;matrix transposition&lt;/a&gt;, but the one that makes the most sense given the code above is to write the columns of the input matrix as the rows of the output matrix.  Remember that &lt;code&gt;accumulate-n&lt;/code&gt; will combine the columns with whatever function we give it, and this part of the exercise is a snap.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (transpose mat)&lt;br /&gt;   (accumulate-n cons null mat))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can test this procedure with the matrix s defined in the exercise above.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (define s (list (list 1 2 3) (list 4 5 6) (list 7 8 9) (list 10 11 12)))&lt;br /&gt;&amp;gt; (transpose s)&lt;br /&gt;((1 4 7 10) (2 5 8 11) (3 6 9 12))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Multiply two matrices&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (matrix-*-matrix m n)&lt;br /&gt;   (let ((cols (transpose n)))&lt;br /&gt;      (map &amp;lt;??&amp;gt; m)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When &lt;a href="http://en.wikipedia.org/wiki/Matrix_multiplication"&gt;multiplying two matrices&lt;/a&gt; &lt;span style="font-style: italic;"&gt;m&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;, the resulting matrix will have the same number of rows as &lt;span style="font-style: italic;"&gt;m&lt;/span&gt; and the same number of columns as &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;.  Each element of the result matrix can be found by taking the dot product of each row of &lt;span style="font-style: italic;"&gt;m&lt;/span&gt; and each column of &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/File:Matrix_multiplication_diagram_2.svg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 313px; height: 275px;" src="http://2.bp.blogspot.com/-KznF_lKOqDo/TbR67bFagrI/AAAAAAAAAY0/K6HiIptK0iQ/s320/Matrix_multiplication_diagram_2.png" alt="Matrix Multiplication" id="BLOGGER_PHOTO_ID_5599235398029705906" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;When viewed this way, it's easy to see that each row the resulting matrix is the product of a row in the first input matrix (&lt;span style="font-style: italic;"&gt;m&lt;/span&gt;) and the entire second input matrix (&lt;span style="font-style: italic;"&gt;n&lt;/span&gt;).  Using this knowledge, we can define multiplication of two matrices in terms of &lt;code&gt;matrix-*-vector&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (matrix-*-matrix m n)&lt;br /&gt;   (let ((cols (transpose n)))&lt;br /&gt;     (map (lambda (row) (matrix-*-vector cols row)) m)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Testing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We have to remember a few rules of matrix algebra that aren't enforced in the procedures we've defined.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;For &lt;code&gt;dot-product&lt;/code&gt;, two vectors can only be multiplied if they're the same length.&lt;/li&gt;&lt;li&gt;For &lt;code&gt;matrix-*-vector&lt;/code&gt;, the vector must be the same length as the number of columns in the matrix.&lt;/li&gt;&lt;li&gt;For &lt;code&gt;matrix-*-matrix&lt;/code&gt;, two matrices A and B can be multiplied only if the number of columns of A matches the number of rows of B.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (define v (list 1 3 -5))&lt;br /&gt;&amp;gt; (define w (list 4 -2 -1))&lt;br /&gt;&amp;gt; (dot-product v w)&lt;br /&gt;3&lt;br /&gt;&amp;gt; (define m (list (list 1 2 3) (list 4 5 6)))&lt;br /&gt;&amp;gt; (define v (list 1 2 3))&lt;br /&gt;&amp;gt; (matrix-*-vector m v)&lt;br /&gt;(14 32)&lt;br /&gt;&amp;gt; (define a (list (list 14 9 3) (list 2 11 15) (list 0 12 17) (list 5 2 3)))&lt;br /&gt;&amp;gt; (define b (list (list 12 25) (list 9 10) (list 8 5)))&lt;br /&gt;&amp;gt; (matrix-*-matrix a b)&lt;br /&gt;((273 455) (243 235) (244 205) (102 160))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Note that the values above are the same as those used as as examples on pages I linked to explaining each operation.  The results above are correct, but you can do a Google search for "&lt;a href="http://www.google.com/search?source=ig&amp;amp;hl=en&amp;amp;rlz=&amp;amp;=&amp;amp;q=matrix+multiplication+calculator&amp;amp;btnG=Google+Search"&gt;matrix multiplication calculator&lt;/a&gt;" to find several online calculators if you want to test with other values.&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/7006144058667705953/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=7006144058667705953" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7006144058667705953?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7006144058667705953?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/04/sicp-236-237-matrix-algebra.html" title="SICP 2.36 &amp; 2.37: Matrix Algebra" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-7HQe_3yyrIY/TbR6UArPpWI/AAAAAAAAAYs/nK9U8Wnj_uo/s72-c/matrix.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0EDRn09cSp7ImA9WhZRE0U.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3215422359843242211</id><published>2011-04-09T17:37:00.003-04:00</published><updated>2011-04-09T17:47:57.369-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-09T17:47:57.369-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="trees" /><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 2.35: Counting the Leaves of a Tree</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.35&lt;/span&gt; asks us to redefine the &lt;code&gt;count-leaves&lt;/code&gt; procedure from section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.2"&gt;2.2.2&lt;/a&gt; as an accumulation.  Our procedure should take the following form:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (count-leaves t)&lt;br /&gt;   (accumulate &amp;lt;??&amp;gt; &amp;lt;??&amp;gt; (map &amp;lt;??&amp;gt; &amp;lt;??&amp;gt;)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When I encounter a problem like this (implement X in terms of Y), I find that it helps to take a look at both procedures side-by-side to see what they have in common.  The &lt;code&gt;count-leaves&lt;/code&gt; procedure just returns 1 when it encounters each leaf node, and recursively combines all those 1s with addition otherwise.&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;; count-leaves from sicp section 2.2.2&lt;br /&gt;(define (count-leaves x)&lt;br /&gt;   (cond ((null? x) 0)&lt;br /&gt;         ((not (pair? x)) 1)&lt;br /&gt;         (else (+ (count-leaves (car x))&lt;br /&gt;                  (count-leaves (cdr x))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;accumulate&lt;/code&gt; procedure takes an operator, and initial  value, and a sequence as its parameters.  It then combines all elements  of the sequence with the initial value using the operator.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;; accumulate from sicp section 2.2.3&lt;br /&gt;(define (accumulate op initial sequence)&lt;br /&gt;   (if (null? sequence)&lt;br /&gt;       initial&lt;br /&gt;       (op (car sequence)&lt;br /&gt;           (accumulate op initial (cdr sequence)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt; The operator and initial value in the case of &lt;code&gt;count-leaves&lt;/code&gt; are pretty easy to guess.  They should be + and 0 respectively.  For its third argument &lt;code&gt;accumulate&lt;/code&gt; is expecting a sequence, and our template is using &lt;code&gt;map&lt;/code&gt;.  Recall that &lt;code&gt;map&lt;/code&gt; takes a function and a list and returns a new list.   The new list is simply the result of the function being applied to each element of the old list.  What we'd really like to accumulate is a sequence of 1s, one for each leaf in the tree.  To implement that we need the help of one more procedure from SICP section 2.2.3.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;; enumerate-tree from sicp 2.2.3&lt;br /&gt;(define (enumerate-tree tree)&lt;br /&gt;   (cond ((null? tree) null)&lt;br /&gt;         ((not (pair? tree)) (list tree))&lt;br /&gt;        (else (append (enumerate-tree (car tree))&lt;br /&gt;                       (enumerate-tree (cdr tree))))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;enumerate-tree&lt;/code&gt; procedure "flattens out" a tree into a sequence of its leaves.  Once we have the tree in the form of a sequence, we just need to define a function for the first argument of &lt;code&gt;map&lt;/code&gt;.  This function should simply return a 1 for any input.  Here's the complete (but very short) solution.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (count-leaves t)&lt;br /&gt;   (accumulate + 0 (map (lambda (x) 1)&lt;br /&gt;                        (enumerate-tree t))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Test it out with trees of different shapes, just to be sure there are no corner cases missed.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;amp;gt; (count-leaves (list))&lt;br /&gt;0&lt;br /&gt;&amp;amp;gt; (count-leaves (list 1 2 3))&lt;br /&gt;3&lt;br /&gt;&amp;amp;gt; (count-leaves (list 1 (list 1 2 3)))&lt;br /&gt;4&lt;br /&gt;&amp;amp;gt; (count-leaves (list (list 1 2) (list 1 2 3) 1))&lt;br /&gt;6&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3215422359843242211/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3215422359843242211" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3215422359843242211?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3215422359843242211?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/04/sicp-235-counting-leaves-of-tree.html" title="SICP 2.35: Counting the Leaves of a Tree" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>1</thr:total></entry><entry gd:etag="W/&quot;DUIBR3k6cSp7ImA9WhZSGEo.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-7543886470086535966</id><published>2011-04-03T17:37:00.003-04:00</published><updated>2011-04-03T20:39:16.719-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-03T20:39:16.719-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="horner" /><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" /><category scheme="http://www.blogger.com/atom/ns#" term="math" /><title>SICP 2.34: Horner's rule</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.34&lt;/span&gt; introduces &lt;a href="http://en.wikipedia.org/wiki/Horner_scheme"&gt;Horner's rule&lt;/a&gt;, an algorithm for the efficient evaluation of polynomial expressions at a given value of &lt;span style="font-style: italic;"&gt;x&lt;/span&gt;.  Horner's rule evaluates a polynomial expression using the fewest possible number of additions and multiplications.&lt;br /&gt;&lt;br /&gt;Let's take a look at a specific example to see how this works.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;4x&lt;sup&gt;3&lt;/sup&gt; + 3x&lt;sup&gt;2&lt;/sup&gt; + 2x + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The terms of the polynomial above can be grouped as follows&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;(4x&lt;sup&gt;3&lt;/sup&gt; + 3x&lt;sup&gt;2&lt;/sup&gt; + 2x) + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Once that grouping is in place it's easier to see that you can now factor out an &lt;span style="font-style: italic;"&gt;x&lt;/span&gt; from the term in parentheses.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;x * (4x&lt;sup&gt;2&lt;/sup&gt; + 3x + 2) + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Now you can apply the same grouping and factoring steps to the term left in parentheses.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;x * (x * (4x + 3) + 2) + 1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This is as far as we can go because another &lt;span style="font-style: italic;"&gt;x&lt;/span&gt; cannot be factored out of the term in the innermost parentheses.&lt;br /&gt;&lt;br /&gt;More generally, Horner's rule says that the polynomial&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:130%;"&gt;a&lt;sub&gt;n&lt;/sub&gt;x&lt;sup&gt;n&lt;/sup&gt; + a&lt;sub&gt;n-1&lt;/sub&gt;x&lt;sup&gt;n-1&lt;/sup&gt; + ... + a&lt;sub&gt;0&lt;/sub&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;can be evaluated as&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:130%;"&gt;((a&lt;sub&gt;n&lt;/sub&gt;x + a&lt;sub&gt;n-1&lt;/sub&gt;)x + ...)x + a&lt;sub&gt;0&lt;/sub&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This reduces the total number of multiplications performed because the exponents in each term of the original polynomial are not computed separately.&lt;br /&gt;&lt;br /&gt;Using Horner's rule, evaluating polynomials can be formulated as an accumulation.  Our task in this exercise is to complete the following implementation, assuming that the coefficients of the polynomial are arranged in a sequence from a&lt;sub&gt;0&lt;/sub&gt; through a&lt;sub&gt;n&lt;/sub&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (horner-eval x coefficient-sequence)&lt;br /&gt;   (accumulate (lambda (this-coeff higher-terms) &amp;lt;??&amp;gt;)&lt;br /&gt;               0&lt;br /&gt;               coefficient-sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Given the framework and assumption above, there really are not a lot of different ways to go about this.  The &lt;code&gt;accumulate&lt;/code&gt; procedure is already doing most of the work for us, recursively accumulating the terms of the polynomial in the order that they're (conveniently) provided.  All we have to do is implement the operator function that gets passed to accumulate.&lt;br /&gt;&lt;br /&gt;The piece that we need to implement is summarized in the text as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;In other words, we start with a&lt;sub&gt;n&lt;/sub&gt;, multiply by &lt;span style="font-style: italic;"&gt;x&lt;/span&gt;, add a&lt;sub&gt;n-1&lt;/sub&gt;, multiply by &lt;span style="font-style: italic;"&gt;x&lt;/span&gt;, and so on, until we reach a&lt;sub&gt;0&lt;/sub&gt;.&lt;/blockquote&gt;&lt;br /&gt;In our lambda, a&lt;sub&gt;0&lt;/sub&gt; through a&lt;sub&gt;n&lt;/sub&gt; are represented by &lt;code&gt;this-coeff&lt;/code&gt;, so all we need to do is add &lt;code&gt;this-coeff&lt;/code&gt; to the accumulation and multiply by &lt;span style="font-style: italic;"&gt;x&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (horner-eval x coefficient-sequence)&lt;br /&gt;   (accumulate (lambda (this-coeff higher-terms)&lt;br /&gt;                 (+ (* x higher-terms) this-coeff))&lt;br /&gt;               0&lt;br /&gt;               coefficient-sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here also is the implementation of &lt;code&gt;accumulate&lt;/code&gt; so you can test the &lt;code&gt;horner-eval&lt;/code&gt; procedure.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (accumulate op initial sequence)&lt;br /&gt;   (if (null? sequence)&lt;br /&gt;       initial&lt;br /&gt;       (op (car sequence)&lt;br /&gt;           (accumulate op initial (cdr sequence)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Let's start with a simpler test case than the one provided in the text and add terms so we can more easily predict what the correct output should be.  The first example below is evaluating the polynomial (1 + 3x) where &lt;span style="font-style: italic;"&gt;x = 2&lt;/span&gt;, and the final example is evaluating (1 + 3x + 5x&lt;sup&gt;3&lt;/sup&gt; + x&lt;sup&gt;5&lt;/sup&gt;), also at &lt;span style="font-style: italic;"&gt;x = 2&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;amp;gt; (horner-eval 2 (list 1 3))&lt;br /&gt;7&lt;br /&gt;&amp;amp;gt; (horner-eval 2 (list 1 3 0))&lt;br /&gt;7&lt;br /&gt;&amp;amp;gt; (horner-eval 2 (list 1 3 0 5))&lt;br /&gt;47&lt;br /&gt;&amp;amp;gt; (horner-eval 2 (list 1 3 0 5 0))&lt;br /&gt;47&lt;br /&gt;&amp;amp;gt; (horner-eval 2 (list 1 3 0 5 0 1))&lt;br /&gt;79&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 an interesting application of Horner's rule, see the solution to &lt;a href="http://programmingpraxis.com/2011/03/28/look-and-say-revisited/"&gt;Look And Say, Revisited&lt;/a&gt; from &lt;a href="http://programmingpraxis.com/"&gt;Programming Praxis&lt;/a&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/7543886470086535966/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=7543886470086535966" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7543886470086535966?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/7543886470086535966?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/04/sicp-234-horners-rule.html" title="SICP 2.34: Horner's rule" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>3</thr:total></entry><entry gd:etag="W/&quot;CEUGRHc5cSp7ImA9WhZTFks.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-8067999676535780570</id><published>2011-03-20T18:49:00.002-04:00</published><updated>2011-03-20T19:03:45.929-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-20T19:03:45.929-04: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" /><category scheme="http://www.blogger.com/atom/ns#" term="lists" /><title>SICP 2.33: List-manipulation operations as accumulations</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.3"&gt;2.2.3  Sequences as Conventional Interfaces&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Section 2.2.3 of SICP introduces the &lt;code&gt;accumulate&lt;/code&gt; procedure, which combines elements of a list given an initial value and an operation to combine them with.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (accumulate op initial sequence)&lt;br /&gt;   (if (null? sequence)&lt;br /&gt;       initial&lt;br /&gt;       (op (car sequence)&lt;br /&gt;           (accumulate op initial (cdr sequence)))))&lt;br /&gt;&lt;br /&gt;&amp;gt; (accumulate + 0 (list 1 2 3 4 5))&lt;br /&gt;15&lt;br /&gt;&amp;gt; (accumulate * 1 (list 1 2 3 4 5))&lt;br /&gt;120&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.33&lt;/span&gt; asks us to fill in the missing expressions in the following procedure definitions to implement some basic list-manipulation operations as accumulations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;map&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (map p sequence)&lt;br /&gt;   (accumulate (lambda (x y) &amp;lt;??&amp;gt;) nil sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;map&lt;/code&gt; procedure should accept a procedure and a list as arguments, and it should apply the procedure to each element of that list.  We can finish the lambda above by making it apply the procedure &lt;code&gt;p&lt;/code&gt; to &lt;code&gt;x&lt;/code&gt;, then &lt;code&gt;cons&lt;/code&gt; that result to the accumulated sequence.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (map p sequence)&lt;br /&gt;   (accumulate (lambda (x y) (cons (p x) y)) null sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Let's also define a couple of simple procedures to test with.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (double x)&lt;br /&gt;   (* 2 x))&lt;br /&gt;(define (square x)&lt;br /&gt;   (* x x))&lt;br /&gt;&lt;br /&gt;&amp;gt; (map double (list 1 2 3 4 5))&lt;br /&gt;(2 4 6 8 10)&lt;br /&gt;&amp;gt; (map square (list 1 2 3 4 5))&lt;br /&gt;(1 4 9 16 25)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;append&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (append seq1 seq2)&lt;br /&gt;   (accumulate cons &amp;lt;??&amp;gt; &amp;lt;??&amp;gt;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;append&lt;/code&gt; procedure accepts two lists as its parameters and simply appends the second list to the end of the first.  My first attempt at this solution was to simply pass the two sequences to &lt;code&gt;accumulate&lt;/code&gt; in their original order, but this gives us the wrong output.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (append seq1 seq2)&lt;br /&gt;   (accumulate cons seq1 seq2))&lt;br /&gt;&lt;br /&gt;&amp;gt; (append (list 1 2 3) (list 4 5 6))&lt;br /&gt;(4 5 6 1 2 3)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This is because of the way the &lt;code&gt;accumulate&lt;/code&gt; procedure works.  Each element of &lt;code&gt;seq2&lt;/code&gt; is being recursively appended to the front of &lt;code&gt;seq1&lt;/code&gt;.  All we need to do to fix this problem is reverse the order in which the lists are passed to &lt;code&gt;accumulate&lt;/code&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (append seq1 seq2)&lt;br /&gt;   (accumulate cons seq2 seq1))&lt;br /&gt;&lt;br /&gt;&amp;gt; (append (list 1 2 3) (list 4 5 6))&lt;br /&gt;(1 2 3 4 5 6)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;length&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (length sequence)&lt;br /&gt;   (accumulate &amp;lt;??&amp;gt; 0 sequence))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This seems like it should be the easiest one of the bunch.  The &lt;code&gt;length&lt;/code&gt; procedure should simply return the length of the initial sequence.  But &lt;code&gt;accumulate&lt;/code&gt; combines each element of a sequence using the operation we pass to it.  How do we get it to just return the length of the sequence?  We can do that by simply giving it an operation that will ignore each element of the sequence, and just increment the accumulated value.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (length sequence)&lt;br /&gt;   (accumulate (lambda (x y) (+ 1 y)) 0 sequence))&lt;br /&gt;&lt;br /&gt;&amp;gt; (length (list 2 4 6))&lt;br /&gt;3&lt;br /&gt;&amp;gt; (length (list 9 8 7 6 5))&lt;br /&gt;5&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/8067999676535780570/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=8067999676535780570" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8067999676535780570?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/8067999676535780570?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/03/sicp-233-list-manipulation-operations.html" title="SICP 2.33: List-manipulation operations as accumulations" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><thr:total>2</thr:total></entry><entry gd:etag="W/&quot;DkAFQH4-eip7ImA9Wx9aFE4.&quot;"><id>tag:blogger.com,1999:blog-9182705499898252496.post-3993596910660334091</id><published>2011-03-06T12:41:00.005-05:00</published><updated>2011-03-06T13:05:11.052-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-06T13:05:11.052-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="data structures" /><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" /><category scheme="http://www.blogger.com/atom/ns#" term="sets" /><category scheme="http://www.blogger.com/atom/ns#" term="lists" /><title>SICP 2.32: Generating Power Sets</title><content type="html">From SICP section &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html#%_sec_2.2.2"&gt;2.2.2  Hierarchical Structures&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exercise 2.32&lt;/span&gt; introduces the concept of the "set of all subsets" of a given set, which you may recognize from mathematics as the &lt;a href="http://en.wikipedia.org/wiki/Powerset"&gt;power set&lt;/a&gt;.  If we have the set &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; = {x, y, z}, then the power set of &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; is:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;P&lt;/span&gt;(&lt;span style="font-style: italic;"&gt;S&lt;/span&gt;) = { {}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z} }&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;There are a couple of details to note:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The empty set {} is a member of every power set.&lt;/li&gt;&lt;li&gt;The original set {x, y, z} is also a member of its own power set.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;In Scheme we can represent a set as a list of distinct elements, and the power set as a list of sets.  In this exercise, we're given the following definition of a procedure that generates the power set of a set, and asked to complete it:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (subsets s)&lt;br /&gt;   (if (null? s)&lt;br /&gt;       (list nil)&lt;br /&gt;       (let ((rest (subsets (cdr s))))&lt;br /&gt;          (append rest (map &amp;lt;??&amp;gt; rest)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If we're given the set &lt;code&gt;(1 2 3)&lt;/code&gt;, then the finished procedure should return:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If you read the Wikipedia Power set article that I linked to earlier, you'll see that there's a &lt;a href="http://en.wikipedia.org/wiki/Powerset#Algorithms"&gt;recursive algorithm for calculating power sets&lt;/a&gt; (which I'll now quote liberally).&lt;br /&gt;&lt;br /&gt;The first step is to define the following operation:&lt;br /&gt;&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 240px; height: 21px; border-style: none;" src="http://4.bp.blogspot.com/-rHfypHO_PEI/TXPI7rdgKyI/AAAAAAAAAYc/8yz-cuju0zI/s320/Powerset-Function.png" alt="" id="BLOGGER_PHOTO_ID_5581025290846481186" border="0" /&gt;&lt;br /&gt;This function takes an element &lt;span style="font-style: italic;"&gt;e&lt;/span&gt; and a set &lt;span style="font-style: italic;"&gt;T&lt;/span&gt;, and returns a set with the element &lt;span style="font-style: italic;"&gt;e&lt;/span&gt; added to each set &lt;span style="font-style: italic;"&gt;X&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;T&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The procedure for generating the power set follows:&lt;br /&gt;&lt;br /&gt;If &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; = {}, the &lt;span style="font-style: italic;"&gt;P&lt;/span&gt;(&lt;span style="font-style: italic;"&gt;S&lt;/span&gt;) = {{}} (the set contaning only the empty set) is returned.&lt;br /&gt;&lt;br /&gt;Otherwise:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Let e be any single element of &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Let &lt;span style="font-style: italic;"&gt;T&lt;/span&gt; be the &lt;a href="http://en.wikipedia.org/wiki/Complement_%28set_theory%29"&gt;relative complement&lt;/a&gt; of {e} in &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;img style="cursor: pointer; width: 230px; height: 21px; border-style: none;" src="http://2.bp.blogspot.com/-nYuZg_WCCK8/TXPJLP68O-I/AAAAAAAAAYk/9L7u55_QKDs/s320/Powerset-Recursive-Function.png" alt="" id="BLOGGER_PHOTO_ID_5581025558331669474" border="0" /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;In other words, the power set of the empty set is the set containing the empty set and the power set of any other set is all the subsets of the set containing some specific element and all the subsets of the set not containing that specific element.&lt;/blockquote&gt;&lt;br /&gt;This is exactly the same procedure defined in the text.  The only part we have to do is finish the initial operation:&lt;br /&gt;&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 240px; height: 21px; border-style: none;" src="http://4.bp.blogspot.com/-rHfypHO_PEI/TXPI7rdgKyI/AAAAAAAAAYc/8yz-cuju0zI/s320/Powerset-Function.png" alt="" id="BLOGGER_PHOTO_ID_5581025290846481186" border="0" /&gt;&lt;br /&gt;The &lt;code&gt;append&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; procedures are already doing much of the work for us.  We just need to define a function that will add an element &lt;span style="font-style: italic;"&gt;e&lt;/span&gt; to the set &lt;span style="font-style: italic;"&gt;X&lt;/span&gt;.  The &lt;code&gt;map&lt;/code&gt; procedure will apply whatever function we give it to each set in rest (&lt;span style="font-style: italic;"&gt;T&lt;/span&gt; in the mathematical definition above).  We can define that using &lt;code&gt;lambda&lt;/code&gt; as follows.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;(define (subsets s)&lt;br /&gt;   (if (null? s)&lt;br /&gt;       (list null)&lt;br /&gt;       (let ((rest (subsets (cdr s))))&lt;br /&gt;          (append rest (map (lambda (x) (cons (car s) x))&lt;br /&gt;                            rest)))))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here we're recursively calling &lt;code&gt;subsets&lt;/code&gt; with &lt;code&gt;(cdr s)&lt;/code&gt;, which will append to that the &lt;code&gt;car&lt;/code&gt; of s (which represents &lt;span style="font-style: italic;"&gt;e&lt;/span&gt; from the mathematical definition) to each subset of &lt;code&gt;(cdr s)&lt;/code&gt;.  The recursion stops when we run out of elements and the empty set is returned.&lt;br /&gt;&lt;br /&gt;We can test it out with the example given.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&amp;gt; (subsets (list 1 2 3))&lt;br /&gt;(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))&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;.</content><link rel="replies" type="application/atom+xml" href="http://www.billthelizard.com/feeds/3993596910660334091/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9182705499898252496&amp;postID=3993596910660334091" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3993596910660334091?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9182705499898252496/posts/default/3993596910660334091?v=2" /><link rel="alternate" type="text/html" href="http://www.billthelizard.com/2011/03/sicp-232-generating-power-sets.html" title="SICP 2.32: Generating Power Sets" /><author><name>Bill the Lizard</name><uri>http://www.blogger.com/profile/09810099093752485841</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_PnLYRqe0k9g/SKywgF43rhI/AAAAAAAAAAQ/0l6VoF8jG0M/S220/lizard-icon.jpeg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-rHfypHO_PEI/TXPI7rdgKyI/AAAAAAAAAYc/8yz-cuju0zI/s72-c/Powerset-Function.png" height="72" width="72" /><thr:total>2</thr:total></entry></feed>
