<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Harry R. Schwartz</title>
  <id>http://127.0.0.1</id>
  <updated>2009-07-21</updated>
  <author>
    <name>hrs</name>
  </author>
  <entry>
    <title>Google+ Circles</title>
    <link rel="alternate" href="http://127.0.0.1/2011/07/10/google-circles/"/>
    <id>http://127.0.0.1/2011/07/10/google-circles/</id>
    <published>2011-07-10</published>
    <updated>2011-07-10</updated>
    <author>
      <name>hrs</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;img src="/images/posts/social-networking-groups.png" title="social networking groups" alt="social networking groups" /&gt;&lt;/p&gt;

&lt;p&gt;Google researcher Paul Adams posted a &lt;a href="http://www.slideshare.net/padday/the-real-life-social-network-v2"&gt;great presentation&lt;/a&gt; on social networking groups last year (and I actually blogged about it then), but now that G+ is on the market, it&amp;rsquo;s interesting to go through it and see how things have actually turned out.&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;&lt;img src="/images/posts/social-networking-groups.png" title="social networking groups" alt="social networking groups" /&gt;&lt;/p&gt;

&lt;p&gt;Google researcher Paul Adams posted a &lt;a href="http://www.slideshare.net/padday/the-real-life-social-network-v2"&gt;great presentation&lt;/a&gt; on social networking groups last year (and I actually blogged about it then), but now that G+ is on the market, it&amp;rsquo;s interesting to go through it and see how things have actually turned out.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>RFC 2324</title>
    <link rel="alternate" href="http://127.0.0.1/2011/02/12/rfc-2324/"/>
    <id>http://127.0.0.1/2011/02/12/rfc-2324/</id>
    <published>2011-02-12</published>
    <updated>2011-02-12</updated>
    <author>
      <name>hrs</name>
    </author>
    <summary type="html">&lt;p&gt;&lt;img src="/images/posts/rfc-2324.png" title="RFC 2324" alt="RFC 2324" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/rfc2324"&gt;RFC 2324&lt;/a&gt; defines the Hyper Text Coffee Pot Control Protocol. HTCPCP is built on top of HTTP, implementing a range of new headers and errors (418 I&amp;rsquo;M A TEAPOT) that enable the intercommunication of networked coffee pots. Manufacturers, take note&amp;mdash;standards-compliance grows the market.&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;&lt;img src="/images/posts/rfc-2324.png" title="RFC 2324" alt="RFC 2324" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tools.ietf.org/html/rfc2324"&gt;RFC 2324&lt;/a&gt; defines the Hyper Text Coffee Pot Control Protocol. HTCPCP is built on top of HTTP, implementing a range of new headers and errors (418 I&amp;rsquo;M A TEAPOT) that enable the intercommunication of networked coffee pots. Manufacturers, take note&amp;mdash;standards-compliance grows the market.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Memoization using Closures</title>
    <link rel="alternate" href="http://127.0.0.1/2011/01/06/memoization-using-closures/"/>
    <id>http://127.0.0.1/2011/01/06/memoization-using-closures/</id>
    <published>2011-01-06</published>
    <updated>2011-01-06</updated>
    <author>
      <name>hrs</name>
    </author>
    <summary type="html">&lt;p&gt;I wrote a little post about &lt;a href="http://www.harryrschwartz.com/2010/12/18/closures-in-python"&gt;how to use closures&lt;/a&gt; in Python a couple weeks ago, but I&amp;rsquo;m not convinced that I really gave a good motivation for why we might want to use them. The example I gave was a little bit simplistic&amp;mdash;-here&amp;rsquo;s a better one&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I wrote a little post about &lt;a href="http://www.harryrschwartz.com/2010/12/18/closures-in-python"&gt;how to use closures&lt;/a&gt; in Python a couple weeks ago, but I&amp;rsquo;m not convinced that I really gave a good motivation for why we might want to use them. The example I gave was a little bit simplistic&amp;mdash;-here&amp;rsquo;s a better one.&lt;/p&gt;

&lt;p&gt;First, we need to talk about &lt;a href="http://en.wikipedia.org/wiki/Memoization"&gt;memoization&lt;/a&gt; (if you&amp;rsquo;re familiar with memoization already, feel free to skip along a bit). Suppose we want to write a function to calculate the n&lt;sup&gt;th  &lt;/sup&gt; &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_number"&gt;Fibonacci number&lt;/a&gt;. We might first write a naïve recursive function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::python
def fib(n):
    if n &amp;lt; 2:
        return n
    else:
        return fib(n - 1) + fib(n - 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This does the job (assuming we give it appropriate input), but it&amp;rsquo;s actually terribly inefficient. Check out the call tree for &lt;code&gt;fib(5)&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/posts/fib-call-tree.png" title="fibonacci call tree" alt="fibonacci call tree" /&gt;&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ve got a few redundant calls here (notably &lt;code&gt;fib(2)&lt;/code&gt; and &lt;code&gt;fib(3)&lt;/code&gt;), and for higher values of &lt;code&gt;n&lt;/code&gt; they really start adding up. As it turns out, this Fibonacci implementation is O(2&lt;sup&gt;n&lt;/sup&gt;). Our elegantly simple algorithm is awful, just awful.&lt;/p&gt;

&lt;p&gt;But we can salvage it! If we were to record our calculated values (by closing over our already-calculated values, say) we could make this thing &lt;em&gt;phenomenally&lt;/em&gt; more efficient.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:::python
def memoized_fib(n):
    values = [0, 1]

    def fib_helper(k):
        if len(values) &amp;gt; k:
            result = values[k]
        else:
            result = fib_helper(k - 1) + fib_helper(k - 2)
            values.append(result)
        return result

    return fib_helper(n)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We&amp;rsquo;re creating a list called &lt;code&gt;values&lt;/code&gt;, for which each entry contains the Fibonacci number associated with its index, starting with the first two. After we&amp;rsquo;ve recursed all the way down the first time, we build up the list as we pop functions off the stack, so subsequent calls to &lt;code&gt;fib_helper&lt;/code&gt; don&amp;rsquo;t really need to do any recursion at all&amp;mdash;-they can just look up the appropriate value in &lt;code&gt;values&lt;/code&gt;. The list &lt;code&gt;values&lt;/code&gt; is hidden inside a closure, so it&amp;rsquo;s protected from the outside world. We certainly could have implemented memoization using a global variable, but why would we if we we don&amp;rsquo;t have to? Our closure provides an equally efficient and more elegant solution to the problem.&lt;/p&gt;

&lt;p&gt;Just to drive home the efficiency gain, &lt;code&gt;memoized_fib(500)&lt;/code&gt; takes 0.014s to run on my machine; &lt;code&gt;fib(500)&lt;/code&gt; is still calculating an hour later. Which makes sense, since we&amp;rsquo;ve replaced an exponential algorithm with a linear one. Feels good.&lt;/p&gt;

&lt;p&gt;And, yes, it&amp;rsquo;s totally true that we could have just calculated the Fibonacci numbers iteratively and avoided the whole fiasco.  But what would we have learned?&lt;/p&gt;
</content>
  </entry>
</feed>
