<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Code Kills - Play</title>
    <link>http://blog.codekills.net/</link>
    <description></description>
    <dc:language>en</dc:language>
    <admin:errorReportsTo rdf:resource="mailto:david@wolever.net" />
    <generator>Serendipity 1.1.3 - http://www.s9y.org/</generator>
    <pubDate>Fri, 30 May 2008 19:08:17 GMT</pubDate>

    <image>
        <url>http://blog.codekills.net/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Code Kills - Play - </title>
        <link>http://blog.codekills.net/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>Python Brain-Teaser</title>
    <link>http://blog.codekills.net/archives/41-Python-Brain-Teaser.html</link>
            <category>Play</category>
            <category>Python</category>
    
    <comments>http://blog.codekills.net/archives/41-Python-Brain-Teaser.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=41</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=41</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;I&#039;m working on pulling some functionality out of one object and putting it in another, and I came across this interesting problem:&lt;/p&gt;

&lt;p&gt;&lt;style type=&quot;text/css&quot;&gt;
/**
 * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
 * (http://qbnz.com/highlighter/ and http://geshi.org/)
 */
.python .de1, .python .de2 {color: #000060; font-weight: normal;}
.python  {white-space: nowrap;border: 1px dotted #a0a0a0; font-family: &#039;Courier New&#039;, Courier, monospace; font-size: 110%; background-color: #f0f0f0; margin: 0; line-height: 110%; padding: 0;color: #000099;}
.python a:link {color: #006;}
.python a:hover {background-color: #d6d6e6;}
.python .head {font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;}
.python .foot {font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;}
.python .imp {font-weight: bold; color: red;}
.python li, .python li.li1 {font-family: &#039;Courier New&#039;, Courier, monospace; color: #000060; background-color: #e0e0e0; padding-bottom: 2px;}
.python .kw1 {color: #ff7700;font-weight:bold;}
.python .kw2 {color: #008000;}
.python .kw3 {color: #dc143c;}
.python .kw4 {color: #0000cd;}
.python .co1 {color: #808080; font-style: italic;}
.python .coMULTI {color: #808080; font-style: italic;}
.python .es0 {color: #000099; font-weight: bold;font-weight: normal;}
.python .br0 {color: black;}
.python .sy0 {color: #66cc66;}
.python .st0 {color: #483d8b;}
.python .nu0 {color: #ff4500;}
.python .me1 {color: black;}
.python .me {1}
&lt;/style&gt;&lt;/p&gt;

&lt;div class=&quot;python&quot;&gt;
&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; Foo:&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; me = &lt;span class=&quot;st0&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; Bar:&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; me = &lt;span class=&quot;st0&quot;&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; get_me&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;me&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;Foo.&lt;span class=&quot;me1&quot;&gt;get_me&lt;/span&gt; = Bar.&lt;span class=&quot;me1&quot;&gt;get_me&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;x = Foo&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&amp;#160;&lt;/div&gt;
&lt;div class=&quot;de1&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;print&lt;/span&gt; x.&lt;span class=&quot;me1&quot;&gt;get_me&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;What does this print?&lt;/p&gt;

&lt;p&gt;And, next question, why is that?&lt;/p&gt;

&lt;p&gt;After lunch I&#039;ll post my thoughts &lt;img src=&quot;http://blog.codekills.net/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://blog.codekills.net/archives/41-Python-Brain-Teaser.html#extended&quot;&gt;Continue reading &quot;Python Brain-Teaser&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 29 May 2008 11:14:57 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/41-guid.html</guid>
    
</item>
<item>
    <title>SSH Connection Sharing</title>
    <link>http://blog.codekills.net/archives/40-SSH-Connection-Sharing.html</link>
            <category>Play</category>
    
    <comments>http://blog.codekills.net/archives/40-SSH-Connection-Sharing.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=40</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=40</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;This tip was originally posted to the &lt;a href=&quot;http://mail.python.org/pipermail/python-dev/2008-May/079499.html&quot;&gt;python-dev&lt;/a&gt; mailing list, so I can&#039;t take one scrap of credit for it.&lt;/p&gt;

&lt;p&gt;Basically, since OpenSSH4, there has been an option to share connections -- that is, once you&#039;ve opened one connection to a host, every subsequent connection is tunneled through the same channel, completely removing the overhead of authentication!&lt;/p&gt;

&lt;p&gt;It&#039;s quite simple, just add this to &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ControlMaster auto
ControlPath ~/.ssh/.%r@%h:%p
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There can be problems if your machine crashes and that file is left lying around...  So adding this to your crontab will fix that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@reboot rm -f .ssh/controls/*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next time: tab completion with scp!&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sat, 17 May 2008 09:35:07 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/40-guid.html</guid>
    
</item>
<item>
    <title>SSH and HTTPS on the same port?!</title>
    <link>http://blog.codekills.net/archives/36-SSH-and-HTTPS-on-the-same-port!.html</link>
            <category>Play</category>
            <category>Python</category>
    
    <comments>http://blog.codekills.net/archives/36-SSH-and-HTTPS-on-the-same-port!.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=36</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;A friend of mine was over the other night, and we were talking about how much we like running SSH on port 443.  It gets you around all but the most insane firewalls, and to anyone but the keenest of observers it just looks like HTTPS traffic.&lt;/p&gt;

&lt;p&gt;But running SSH over port 443 makes it particularly difficult to run a secure web server as well.&lt;/p&gt;

&lt;p&gt;So what can be done?&lt;/p&gt;

&lt;p&gt;Well, it turns out that when an SSH client initiates a connection, it waits for the server to send a banner (&lt;code&gt;SSH-1.99-OpenSSH_4.7&lt;/code&gt;, for example) before beginning the secure negotiation.  Browsers, on the other hand, just go right ahead and begin the secure negotiation.&lt;/p&gt;

&lt;p&gt;Knowing this, it didn&#039;t take long to formulate a plan: write a little program which will listen on 443.  When it gets a connection, it figures out if the remote end is trying to speak SSH or HTTPS, makes the appropriate connection on the local end, the passes the data between the two.&lt;/p&gt;

&lt;p&gt;It only took a couple of hours to write a &lt;a href=&quot;http://wolever.net/~wolever/sstp/sstp.py&quot;&gt;small proof-of-concept&lt;/a&gt;... And, believe it or not, it even works! &lt;small&gt;Disclaimer: this particular implementation is not quite suitable for any real use.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Anyway, this may not be the most efficient way of doing things... But that&#039;s no matter.  It&#039;s still neat &lt;img src=&quot;http://blog.codekills.net/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Code: &lt;a href=&quot;http://wolever.net/~wolever/sstp/sstp.py&quot;&gt;sstp.py&lt;/a&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 11 Apr 2008 17:38:16 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/36-guid.html</guid>
    
</item>
<item>
    <title>Problem E - Enhancing IPSC Rules: Rock Paper Scissors with PNGs</title>
    <link>http://blog.codekills.net/archives/18-Problem-E-Enhancing-IPSC-Rules-Rock-Paper-Scissors-with-PNGs.html</link>
            <category>Play</category>
    
    <comments>http://blog.codekills.net/archives/18-Problem-E-Enhancing-IPSC-Rules-Rock-Paper-Scissors-with-PNGs.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=18</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=18</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;table border=&quot;1&quot; align=&quot;right&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; style=&quot;background: white;&quot;&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot; valign=&quot;top&quot;&gt;
&lt;img src=&quot;http://images.wolever.net/blog/e0.png&quot; alt=&quot;Rock paper scissors in PNG form&quot; /&gt;&lt;br /&gt;
Rock paper scissors in PNG form&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;At this point, it seems like the Facebook problems have started to go down hill. Even when Ted and I combine our attention spans, we just can&#039;t quite make it through the descriptions. To make matters worse, the only short problem left, &lt;a href=&quot;http://www.facebook.com/jobs_puzzles/?puzzle_id=6&quot;&gt;Easy Puzzle Mountain&lt;/a&gt;, isn&#039;t actually all that easy...&lt;/p&gt;

&lt;p&gt;So what ever will we do on a lovely Saturday night?  Well, why not revisit an older problem.  This time, it is courtesy of the &lt;a href=&quot;http://ipsc.ksp.sk/&quot;&gt;IPSC&lt;/a&gt;&lt;sup&gt;1&lt;/sup&gt;: &lt;a href=&quot;http://ipsc.ksp.sk/contests/ipsc2007/real/problems/e.php&quot;&gt;Problem E - Enhancing IPSC Rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The problem is simple: the input is a JPEG with many pairs of rocks, papers and scissors. Each pair represents one round of &lt;a href=&quot;http://en.wikipedia.org/wiki/Rock,_Paper,_Scissors&quot;&gt;Rock Paper Scissors&lt;/a&gt;.  You must figure out who won each round (and ultimately the game).&lt;/p&gt;

&lt;p&gt;As normal for the IPSC, it was possible to solve the simple data set by hand -- each image had about 10 rounds each.  The hard data set, on the other hand... Well, you can see for yourself.&lt;/p&gt;

&lt;table border=&quot;1&quot; width=&quot;20&quot; align=&quot;right&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; style=&quot;background: white;&quot;&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot; valign=&quot;top&quot;&gt;
10% of one hard dataset.  There are 22 sets in total.&lt;br /&gt;
&lt;img src=&quot;http://images.wolever.net/blog/e2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;We quickly decided that it would be silly to try and examine the shape of each object, so we decided to focus on the color.&lt;/p&gt;

&lt;p&gt;Looking at the color, it&#039;s easy to tell the difference between the rocks and everything else: they are really dark, everything else is really bright.  We called this the luminosity&lt;sup&gt;2&lt;/sup&gt;, and it is simple to obtain: simply add the red, green and blue channels of each pixel&lt;sup&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The next problem we had was telling the difference between paper and scissors.  Their &quot;luminosity&quot; is similar, and probably not enough to make a sure match.  Fortunately, the paper was fairly bland and the scissors were fairly colorful.  We came up with a metric called &quot;color delta&quot; to measure this.  The formula we used simple: &lt;code&gt;color_delta = abs(red - green) + abs(red - blue) + abs(blue - green)&lt;/code&gt; (where &lt;code&gt;abs(x)&lt;/code&gt; is the absolute value of &lt;code&gt;x&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Alright, great.  So now we have a method of distinguishing between rocks, papers and scissors... But how do I read the file? I have never worked with graphics before.  The Python graphics libraries seemed intimidating, and I&#039;ll be darned if I&#039;m also going to decode the PNGs.&lt;/p&gt;

&lt;p&gt;Fortunately, I had the presence of mind to remember the &lt;a href=&quot;http://en.wikipedia.org/wiki/Portable_pixmap&quot;&gt;PNM&lt;/a&gt; format.  The Wikipedia page has more information, but all that&#039;s important for now is that the P stands for Portable, and this portability is due to the fact that it uses flat ASCII to describe an image.  Nothing could be easier to parse.&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;bash&quot; style=&quot;text-align: left&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;for&lt;/span&gt; FILE &lt;span style=&quot;color: #b1b100;&quot;&gt;in&lt;/span&gt; *.png&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;do&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; convert &lt;span style=&quot;color: #0000ff;&quot;&gt;$FILE&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;,.pnm&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;done&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;After this, the code came surprisingly quickly...  And, short of an incredibly stupid bug (I used something along the lines of &lt;code&gt;side = count / width % 2&lt;/code&gt; to figure out which side of the image was being processed),  it even worked!  I was able to plot the output (which was the luminosity, color delta pairs) in gnuplot and see a strong correlation.&lt;/p&gt;

&lt;p&gt;To figure out what each point was, I simply opened up one of the files in Photoshop and cut out all the items but the scissors, then all the items but papers.  After adding these to the plot, it was simple to tell which group was which.&lt;/p&gt;

&lt;table border=&quot;1&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; style=&quot;background: white&quot;&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot; valign=&quot;top&quot;&gt;
&lt;img src=&quot;http://images.wolever.net/blog/plot.png&quot; alt=&quot;The final plot&quot; /&gt;&lt;br /&gt;
The final plot. Red points are data points, green points are papers from the training set and blue points are scissors from the training set.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;And that is it &lt;img src=&quot;http://blog.codekills.net/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Code and sample data can be found at &lt;a href=&quot;http://blog.codekills.net/code/e/&quot;&gt;/code/e/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;1: On a side note, the IPSC is a great programming/problem solving contest.  I have written it for the past three of four years, and every time it&#039;s a lot of fun.&lt;/p&gt;

&lt;p&gt;2: Yes, I realize that this is completely incorrect. Brightness would be much more appropriate.&lt;/p&gt;

&lt;p&gt;3: In actuality, I ended up using &lt;code&gt;(255*3)-(r+g+b)&lt;/code&gt; so that white (empty) pixels would have a value of 0.
&lt;/small&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sat, 21 Jul 2007 23:33:35 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/18-guid.html</guid>
    
</item>
<item>
    <title>Solving Gridflip</title>
    <link>http://blog.codekills.net/archives/16-Solving-Gridflip.html</link>
            <category>Facebook</category>
            <category>Play</category>
    
    <comments>http://blog.codekills.net/archives/16-Solving-Gridflip.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=16</wfw:comment>

    <slash:comments>10</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=16</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;Ted and I had so much fun solving &lt;a href=&quot;http://blog.codekills.net/archives/14-Optimal-Movie-Seating-Puzzle.html&quot;&gt;the last Facebook problem&lt;/a&gt; that we decided to do another this weekend: &lt;a href=&quot;http://www.facebook.com/jobs_puzzles/?puzzle_id=9&quot;&gt;gridflip&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The problem is simple: you are given a grid of numbers, some positive and some negative.  The goal is to minimize the sum of the grid, while keeping the sums of the individual rows and columns positive.  The only operation that can be performed is flipping the sign of the individual rows of columns.  For instance, given the grid:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; [  2  -3 ] -1
 [ -3   5 ]  2
   -1   2    2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A flip to the first row and the first column would result in the grid:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; [ -2   3 ]  1
 [ -3   5 ]  2 # After flipping the first row
   -5   8    6

 [  2   3 ]  5
 [  3   5 ]  8 # After flipping the first column
    5   8   26
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the best solution for this grid, because it is the only solution where the sums of all the rows and columns are positive.&lt;/p&gt;

&lt;p&gt;The solution we came up with for this problem was almost as simple: for every possible combination of flipped/not flipped columns&lt;sup&gt;1&lt;/sup&gt;, make sure that every row is positive.  If, after making the sum of every row positive, the sum of every column is positive, the grid is a contender for the smallest sum.&lt;/p&gt;

&lt;p&gt;Now, there is one small problem: rows which have a sum of zero.  If a row&#039;s sum is zero, a flip won&#039;t change the value of the row, but it will change the value of the columns.  The obvious solution is simply to keep track of which rows have a sum of zero, then try flipping them... And that&#039;s exactly what we did.&lt;/p&gt;

&lt;p&gt;Now, the biggest downside to this algorithm is that it runs in &lt;code&gt;O(2&lt;/code&gt;&lt;sup&gt;&lt;code&gt;n&lt;/code&gt;&lt;/sup&gt;&lt;code&gt;)&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the shortest side of the grid... But in practice, even my &lt;a href=&quot;http://blog.codekills.net/code/facebook/gridflip/gridflip.py&quot;&gt;less-than-optimal Python code&lt;/a&gt; could solve the &quot;large&quot; data set in less than three seconds (&lt;a href=&quot;http://blog.codekills.net/code/facebook/gridflip/gridflip.cs&quot;&gt;Ted&#039;s C# code&lt;/a&gt; was almost instant).&lt;/p&gt;

&lt;p&gt;It makes me wonder, though, is there any way to speed this up?&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;http://blog.codekills.net/code/facebook/gridflip&quot;&gt;/code/facebook/gridflip/&lt;/a&gt; for source code and test grids.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;1: Columns for simplicity -- the actual code makes sure there are fewer columns than rows by transposing the grid.&lt;/small&gt;&lt;/p&gt;
 &lt;br /&gt;&lt;a href=&quot;http://blog.codekills.net/archives/16-Solving-Gridflip.html#extended&quot;&gt;Continue reading &quot;Solving Gridflip&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 05 Jul 2007 17:45:31 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/16-guid.html</guid>
    
</item>
<item>
    <title>Sorting out Sorting</title>
    <link>http://blog.codekills.net/archives/13-Sorting-out-Sorting.html</link>
            <category>Play</category>
    
    <comments>http://blog.codekills.net/archives/13-Sorting-out-Sorting.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=13</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=13</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;Back in grade 10, my high school computer science teacher showed us a video called Sorting out Sorting.  Produced at U of T in 1981&lt;sup&gt;1&lt;/sup&gt;, it shows how different sorting algorithms work and compares their runtime.&lt;/p&gt;

&lt;p&gt;It was very exciting to see it again this morning!  Check out &lt;a href=&quot;http://www.youtube.com/watch?v=F3oKjPT5Khg&quot;&gt;Sorting out Sorting on YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;1: &lt;a href=&quot;http://www.cs.princeton.edu/~ah/alg_anim/animation/bibliography3_8.html#SOS&quot;&gt;http://www.cs.princeton.edu/~ah/alg_anim/animation/bibliography3_8.html#SOS&lt;/a&gt;
&lt;/small&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Wed, 20 Jun 2007 10:34:17 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/13-guid.html</guid>
    
</item>
<item>
    <title>Amazon S3 (or, How I Solved My Image Hosting Woes)</title>
    <link>http://blog.codekills.net/archives/11-Amazon-S3-or,-How-I-Solved-My-Image-Hosting-Woes.html</link>
            <category>Play</category>
            <category>Python</category>
    
    <comments>http://blog.codekills.net/archives/11-Amazon-S3-or,-How-I-Solved-My-Image-Hosting-Woes.html#comments</comments>
    <wfw:comment>http://blog.codekills.net/wfwcomment.php?cid=11</wfw:comment>

    <slash:comments>6</slash:comments>
    <wfw:commentRss>http://blog.codekills.net/rss.php?version=2.0&amp;type=comments&amp;cid=11</wfw:commentRss>
    

    <author>david@wolever.net (David Wolever)</author>
    <content:encoded>
    &lt;p&gt;A couple months ago, I read Jeff Atwood&#039;s article on &lt;a href=&quot;http://www.codinghorror.com/blog/archives/000808.html&quot;&gt;Using Amazon S3 as an Image Hosting Service&lt;/a&gt;, but because my favicon does not does not generate &lt;a href=&quot;http://www.hanselman.com/blog/FavIconicoCanBeABandwidthHog.aspx&quot;&gt;27 GBs of traffic a month&lt;/a&gt;, I didn&#039;t think much of it.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(if you&#039;re scratching your head wondering what &lt;a href=&quot;http://www.amazon.com/gp/browse.html?node=16427261&quot;&gt;Amazon&#039;s S3&lt;/a&gt; is, I&#039;ll do my best to explain.  It stands for Simple Storage Service, and it is just that: a simple service that allows you to store data. That data (or &quot;those files&quot;, if you wish) can be world-readable (from a web browser) or private (many people are &lt;a href=&quot;http://www.google.ca/search?q=amazon+S3+backup&quot;&gt;using it for backup&lt;/a&gt;).  It&#039;s targeted at developers (Amazon only provides a set of APIs -- all GUIs are 3rd party) and it is dirt cheep: only $0.15 a gigabyte.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Then, a few weeks ago, I was taking some pictures of my sister&#039;s soccer practice, and realized that I needed some place to put them.  After looking at a couple of cheep hosting plans, I decided that I didn&#039;t like them; $5 a month isn&#039;t much, but that&#039;s still $60 a year for a whole lot of space I won&#039;t be using.  Then I remembered S3.&lt;/p&gt;

&lt;p&gt;After a night of playing around, I figured that it should be pretty simple.  Write a script that will go through an HTML file looking for images, then upload them one at a time, replacing the links as it goes. &lt;a href=&quot;http://wolever.net/~wolever/html2s3.py&quot;&gt;html2s3&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;It turns out that the S3 library provided by Amazon is very easy to use, with most of my time spent correcting file paths.  A couple of neat bits:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;python&quot; style=&quot;text-align: left&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #dc143c;&quot;&gt;parser&lt;/span&gt; = OptionParser&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;usage = &lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;usage: %prog [options] [FILES]&lt;span style=&quot;color: #000099; font-weight: bold;&quot;&gt;\n&lt;/span&gt;Will process ...&quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #dc143c;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;add_option&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;-b&quot;&lt;/span&gt;, &lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;--bucket&quot;&lt;/span&gt;, action=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;store&quot;&lt;/span&gt;, dest=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;bucket&quot;&lt;/span&gt;, &lt;span style=&quot;color: #008000;&quot;&gt;help&lt;/span&gt;=...&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #dc143c;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;add_option&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;-k&quot;&lt;/span&gt;, &lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;--key-prefix&quot;&lt;/span&gt;, dest=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;remote_base_path&quot;&lt;/span&gt;, &lt;span style=&quot;color: #008000;&quot;&gt;help&lt;/span&gt;=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;Prefix key ...&quot;&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #dc143c;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;add_option&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;-n&quot;&lt;/span&gt;, &lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;--no-backup&quot;&lt;/span&gt;, dest=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;no_backup&quot;&lt;/span&gt;, action=&lt;span style=&quot;color: #483d8b;&quot;&gt;&quot;store_true&quot;&lt;/span&gt; ...&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;options, args&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt; = &lt;span style=&quot;color: #dc143c;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;parse_args&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;I had seen &lt;code&gt;OptionParser&lt;/code&gt; before, but never used it.  It&#039;s so simple, though, that I think I&#039;m going to use it quite a bit more frequently.&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;python&quot; style=&quot;text-align: left&quot;&gt;&lt;br /&gt;&amp;#160; source = args &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;or&lt;/span&gt; &lt;span style=&quot;color: #dc143c;&quot;&gt;sys&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;stdin&lt;/span&gt;.&lt;span style=&quot;color: black;&quot;&gt;xreadlines&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;for&lt;/span&gt; line &lt;span style=&quot;color: #ff7700;font-weight:bold;&quot;&gt;in&lt;/span&gt; source:&lt;br /&gt;&amp;#160; &amp;#160; process_entry&lt;span style=&quot;color: black;&quot;&gt;&amp;#40;&lt;/span&gt;line&lt;span style=&quot;color: black;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;One thing I loved about C was the ability to use assignment in loops (&lt;code&gt;while (fgets(buf, sizeof(buf), stdin) != EOF)&lt;/code&gt;), but stdin.xreadlines() does the same sort of thing.&lt;/p&gt;

&lt;p&gt;Update: When I moved the script over to my server, it started telling me that I didn&#039;t have permission to list the bucket.  So I started digging in to it a bit, and found out that I was getting the error &lt;code&gt;RequestTimeTooSkewed&lt;/code&gt;.  It turns out that I forgot to turn my server&#039;s clock back last daylight savings... D&#039;oh!&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 12 Jun 2007 12:19:42 -0400</pubDate>
    <guid isPermaLink="false">http://blog.codekills.net/archives/11-guid.html</guid>
    
</item>

</channel>
</rss>