<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5265869129831265924</id><updated>2012-05-13T08:46:08.568-04:00</updated><category term='oil'/><category term='appengine'/><category term='javascript'/><category term='python'/><category term='law'/><category term='Linux'/><category term='programming'/><category term='spotlight'/><category term='quotes'/><category term='freebsd'/><category term='storage'/><category term='vim'/><category term='Ubuntu'/><category term='projects'/><category term='productivity'/><category term='health'/><category term='xmonad'/><category term='ZFS'/><category term='humor'/><title type='text'>log.brandonthomson.com</title><subtitle type='html'>Code, commentary, and (occasionally) useful stuff.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default?start-index=26&amp;max-results=25'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>107</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-5653876515219203410</id><published>2011-07-08T09:45:00.002-04:00</published><updated>2011-07-08T09:47:17.895-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='projects'/><title type='text'>Blogger: Having posts skip the RSS feed</title><content type='html'>&lt;p&gt;Turns out you can make new posts not show up in the RSS feed in Blogger, but
the only way to to do it is to backdate them far enough that, chronologically,
they are more than 8 entries ago.&lt;/p&gt;

&lt;p&gt;Oi, working around the limitations of closed platforms is always frustrating.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-5653876515219203410?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/5653876515219203410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/07/blogger-having-posts-skip-rss-feed.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5653876515219203410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5653876515219203410'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/07/blogger-having-posts-skip-rss-feed.html' title='Blogger: Having posts skip the RSS feed'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-1844719083182117785</id><published>2011-06-29T11:41:00.002-04:00</published><updated>2011-06-29T11:42:32.478-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spotlight'/><title type='text'>Spotlight on Open Source: youtube-dl</title><content type='html'>&lt;p&gt;&lt;a href="http://rg3.github.com/youtube-dl/"&gt;youtube-dl&lt;/a&gt; by Ricardo Garcia Gonzalez (Public Domain)&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;One of the things I really enjoy watching on Youtube are "Let's Play's": regular people recording their play-throughs of (typically classic) video games in an episodic format. I have a lot of childhood memories associated with various 8- and 16-bit titles, so it's always a fun trip down memory lane.&lt;/p&gt;

&lt;p&gt;Unfortunately Youtube's playlist interface can be summarily described as "awful" and the interface still does not support altering playback speed for most videos. Worse, Adobe Flash just sucks and doesn't belong anywhere near Linux.&lt;/p&gt;

&lt;p&gt;I used to use an extension for my web browser to download individual videos, but &lt;a href="http://rg3.github.com/youtube-dl/"&gt;youtube-dl&lt;/a&gt; makes life much easier by letting you download an entire playlist into a directory. You can even resume downloading where you left off so it's easy to get partial playlists or keep your local archive up to date as new videos are added.&lt;/p&gt;

&lt;p&gt;Is it worth it to waste disk space storing videos you can download for free whenever you want? Of course! For one thing, it's nice if you have a monthly download quota like I do since playlists with HD videos can often exceed 20GB: you can download some content in advance to watch later when you might be near the quota.&lt;/p&gt;

&lt;p&gt;For another, mplayer is far superior to Youtube's player. You can set a default (faster) playback speed and apply video filters like unsharp mask and add noise which really improve perceived video quality, or use vdpau to get hardware acceleration for 1080p movies.&lt;/p&gt;

&lt;p&gt;Finally, you can move each file into a "watched" subfolder as you finish watching it, which I find to be far more intuitive than any of Youtube's playlist-type features.&lt;/p&gt;

&lt;p&gt;The only thing I thought &lt;a href="http://rg3.github.com/youtube-dl/"&gt;youtube-dl&lt;/a&gt; was missing was support for parallel downloads of all files in a playlist: Youtube limits standard defintion video downloads to about 100k/s, so if you want to max out your connection, parallel downloads are necessary. I tend to run it in GNU screen on a server, though, so it doesn't bother me if it takes a while to finish.&lt;/p&gt;

&lt;p&gt;Overall, &lt;a href="http://rg3.github.com/youtube-dl/"&gt;youtube-dl&lt;/a&gt; is a fantastic script. Thanks, Ricardo!&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;Spotlight on Open Source is a periodic feature where I highlight a piece of
open-source software that is making my life better. If you liked this entry,
why not 
&lt;a href="/search/label/spotlight"&gt;view the previous features&lt;/a&gt;? Open-source
projects usually benefit from publicity, so I encourage you to spread the word
as well!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-1844719083182117785?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/1844719083182117785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/06/spotlight-on-open-source-youtube-dl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1844719083182117785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1844719083182117785'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/06/spotlight-on-open-source-youtube-dl.html' title='Spotlight on Open Source: youtube-dl'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-5674341777355059003</id><published>2011-06-23T11:54:00.002-04:00</published><updated>2011-06-23T11:55:44.950-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quotes'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>A quote: Concise, to-the-purpose solutions</title><content type='html'>&lt;blockquote&gt;
&lt;p&gt;I'm glad I can program, because personal programming in the small is fertile ground and tremendously useful. [...] Writing concise to-the-purpose solutions is a primary reason for programming in the twenty-first century.&lt;/p&gt;
&lt;p class="bt-quote-attrib"&gt;&amp;mdash; &lt;a href="http://prog21.dadgum.com/56.html"&gt;James Hague&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Indeed. One of the best parts of taking the effort to learn about software is that you get to customize your tools to behave exactly how you want them to instead of being stuck with a few options someone thought were most likely to appeal to the unwashed masses.&lt;/p&gt;

&lt;p&gt;Working is a lot more enjoyable when your tools do exactly what you want.&lt;/p&gt;

&lt;p&gt;Don't get me wrong; I like the trend towards app stores, too. It's just that, for most of what I want to do, There's No App For That&amp;trade;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-5674341777355059003?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/5674341777355059003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/06/quote-concise-to-purpose-solutions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5674341777355059003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5674341777355059003'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/06/quote-concise-to-purpose-solutions.html' title='A quote: Concise, to-the-purpose solutions'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-2453080534263186388</id><published>2011-06-15T02:37:00.005-04:00</published><updated>2011-06-15T02:43:49.659-04:00</updated><title type='text'>Hyphenator on Blogger</title><content type='html'>&lt;p&gt;
It feels a little kludgy, but I managed to get &lt;a href="http://code.google.com/p/hyphenator/"&gt;Hyphenator&lt;/a&gt; installed on this blog so the text can be justified.
&lt;/p&gt;

&lt;p&gt;
I'm not sure if editing your template to add the &lt;code&gt;hyphenate&lt;/code&gt; class to the &lt;code&gt;post-body entry-content&lt;/code&gt; div is the only way to do it, but it worked for me. For some reason I already had my template under version control so it's pretty easy for me to add stuff to it even though I run into bugs in Blogger every time I try to update the template.
&lt;/p&gt;

&lt;p&gt;
But I'll spare you the boring details of my complaints about Blogger.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-2453080534263186388?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/2453080534263186388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/06/hyphenator-on-blogger.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2453080534263186388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2453080534263186388'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/06/hyphenator-on-blogger.html' title='Hyphenator on Blogger'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-673255781880023077</id><published>2011-06-14T16:01:00.000-04:00</published><updated>2011-06-14T16:01:00.588-04:00</updated><title type='text'>Air conditioning affects line voltage</title><content type='html'>This is kinda neat. As May has turned into June and more people are using air conditioning, the line voltage detected by my UPS has started to dip during the day. It's the orange line at the top in this image:&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/-mVHKNaWFQWY/TfUbk2aQdoI/AAAAAAAAAYc/p1XX09X2jFQ/apcupsd_ww-month.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="216" src="http://3.bp.blogspot.com/-mVHKNaWFQWY/TfUbk2aQdoI/AAAAAAAAAYc/p1XX09X2jFQ/apcupsd_ww-month.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The minimum line voltage corresponds to about 4PM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-673255781880023077?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/673255781880023077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/06/air-conditioning-affects-line-voltage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/673255781880023077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/673255781880023077'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/06/air-conditioning-affects-line-voltage.html' title='Air conditioning affects line voltage'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-mVHKNaWFQWY/TfUbk2aQdoI/AAAAAAAAAYc/p1XX09X2jFQ/s72-c/apcupsd_ww-month.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-1359220212700631926</id><published>2011-06-12T13:22:00.005-04:00</published><updated>2011-06-12T13:33:11.762-04:00</updated><title type='text'>Terrible, then merely bad</title><content type='html'>Over on the &lt;a href="http://googlecode.blogspot.com/2011/05/spring-cleaning-for-some-of-our-apis.html"&gt;post where Google announced they were going to shut down the Translate API&lt;/a&gt;, I found this (abridged) comment:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;Google is like NASA of the internet - they have the best and brightest on their payroll - and I'm not just talking about their developers. If there was truly an abuse to the API they would have developed a way to handle it without shutting it down. So, in this case, the abuse is nothing more than a smoke screen.&lt;br /&gt;
&lt;br /&gt;
If you woke up one morning and found out that Google is going to charge for their API you would start bashing Google left and right for charging for something that used to be free and their PR would flat line - essentially - they would look like the monster taking candy from a child.&lt;/blockquote&gt;&lt;br /&gt;
I don't know whether he's right and it was an intentional move, but he is right that the PR tends to work better if you announce something terrible and then recant and announce something merely bad which looks good in comparison to your original announcement. &lt;br /&gt;
&lt;br /&gt;
Recently Google's App Engine team also announced major pricing changes which looked like a disaster for many of us, and then changed their mind about some of the details to make them more favorable. I think the overall sentiment in the community is now actually better than it would have been if they had simply announced the latest (better) details in the first place and then not made any changes.&lt;br /&gt;
&lt;br /&gt;
Doing this sort of thing intentionally is probably a bit unethical, but I don't doubt that it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-1359220212700631926?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/1359220212700631926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/06/terrible-then-merely-bad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1359220212700631926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1359220212700631926'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/06/terrible-then-merely-bad.html' title='Terrible, then merely bad'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-8761870044066502953</id><published>2011-05-21T02:29:00.006-04:00</published><updated>2011-05-21T02:31:13.822-04:00</updated><title type='text'>Comcast Bandwidth Usage Python Script</title><content type='html'>It's not exactly easy to find through Google, but Jared Hobbs has written a Python script which can log in to Comcast's website and write your current bandwidth usage to stdout. A really handy thing to have tied into your status bar if you are a heavy user! Get it here:&amp;nbsp;&lt;a href="http://thehobbsfamily.net/archive2011/comcappy-comcast-internet-usage-script/"&gt;http://thehobbsfamily.net/archive2011/comcappy-comcast-internet-usage-script/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-8761870044066502953?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/8761870044066502953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/05/comcast-bandwidth-usage-python-script.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8761870044066502953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8761870044066502953'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/05/comcast-bandwidth-usage-python-script.html' title='Comcast Bandwidth Usage Python Script'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-3361799096266285570</id><published>2011-04-27T06:50:00.000-04:00</published><updated>2011-04-27T06:50:05.890-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Closure Compiler: Removing console log statements</title><content type='html'>&lt;a
href="https://groups.google.com/forum/#!msg/closure-compiler-discuss/0S2cs-zvYro/p9oFWb-zyDwJ"&gt;This
thread&lt;/a&gt; has a great solution for stripping console.log() calls using the closure
compiler:

&lt;pre class="brush:js"&gt;
var
  /** @define {boolean} */ DEBUG = true,

console_log = function(var_args) {
  if (DEBUG) {
    console.log.apply(console, arguments);
  }
};
&lt;/pre&gt;

&lt;p&gt;
(Now you must use console_log calls instead of console.log.)
&lt;/p&gt;

&lt;p&gt;I tested it and it works great. There are some other ideas &lt;a
href="http://stackoverflow.com/questions/2934509/exclude-debug-javascript-code-during-minification"&gt;on stackoverflow&lt;/a&gt; but many of them don't work. I think this is the best way.&lt;/p&gt;

&lt;p&gt;Incidentally @define will allow you to pass a flag to the compiler to enable/disable the log statements but I prefer to just change the constant in the JavaScript file since make will then automatically detect the change and rebuild without needing any changes to the Makefile.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-3361799096266285570?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/3361799096266285570/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/04/closure-compiler-removing-console-log.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/3361799096266285570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/3361799096266285570'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/04/closure-compiler-removing-console-log.html' title='Closure Compiler: Removing console log statements'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-4450577298400609389</id><published>2011-04-26T16:05:00.000-04:00</published><updated>2011-04-26T16:18:06.511-04:00</updated><title type='text'>The Future of Firefox</title><content type='html'>Recently I tried to create my first Firefox addon. It was not a pleasant experience. Chromium's API makes such things as adding an item to the browser context menu simpler and the debugging process is easier to understand.&lt;br /&gt;
&lt;br /&gt;
This is not to knock on the fine folks working at Mozilla; I read somewhere that Firefox's codebase has been touched by so many people that it is truly a cruel and unusual form of torture trying to understand and modify it. I believe it.&lt;br /&gt;
&lt;br /&gt;
Still, it makes me sad. I like the idea of contributing to the software ecosystem around a browser made by a non-profit organization. I am just finding it hard to justify it on practical grounds.&lt;br /&gt;
&lt;br /&gt;
If I am having these doubts, maybe other people are too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-4450577298400609389?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/4450577298400609389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/04/future-of-firefox.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/4450577298400609389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/4450577298400609389'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/04/future-of-firefox.html' title='The Future of Firefox'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-5187346397046913162</id><published>2011-04-21T02:11:00.000-04:00</published><updated>2011-04-21T02:11:23.771-04:00</updated><title type='text'>CLRS bibtex entry (3rd edition)</title><content type='html'>Following on the work of &lt;a href="http://timmiesmith.blogspot.com/2007/07/be-kind-to-nerds-make-your-bibtex-entry.html"&gt;Timmie Smith&lt;/a&gt;, here is some bibtex for the 3rd edition of CLRS.

&lt;pre class="brush:plain"&gt;
@book{clrs,
  author = "T.~H. Cormen and C.~E. Leiserson and R.~L. Rivest and C.~Stein",
  edition = "3rd",
  publisher = "The MIT Press",
  title = "Introduction to Algorithms",
  year = "2009",
  isbn = "978-0-262-03384-8"
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-5187346397046913162?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/5187346397046913162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/04/clrs-bibtex-entry-3rd-edition.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5187346397046913162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5187346397046913162'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/04/clrs-bibtex-entry-3rd-edition.html' title='CLRS bibtex entry (3rd edition)'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-3284727864959063259</id><published>2011-04-12T14:39:00.000-04:00</published><updated>2011-04-12T14:39:05.219-04:00</updated><title type='text'>Changing Ubuntu Lucid's Boot Drive with Grub 2</title><content type='html'>&lt;p&gt;I recently bought an SSD for my workstation and wanted to boot from the
SSD instead of spinning disk. It used to be you could do this simply by
copying all the files from your current &lt;code&gt;/&lt;/code&gt; partition over to the
new partiton, mucking about in &lt;code&gt;/etc/fstab&lt;/code&gt; a bit, (optionally)
installing grub in the MBR of the new disk, and then changing the boot order
in the BIOS to put the disk with your new partition at the top of the list.
This would cause grub to see your new disk as &lt;code&gt;hd0&lt;/code&gt; and maybe you
didn't even need to change &lt;code&gt;/etc/fstab&lt;/code&gt; either if the number of the
new partition was the same as the old one.&lt;/p&gt;

&lt;p&gt;It turns out that with Grub 2, changing the boot order of disks in the
BIOS is no longer sufficient because Grub 2 uses UUIDs for all entries! So
even after you change the boot order it will still find the old disk.&lt;/p&gt;

&lt;p&gt;The good news is that you can easily solve this by search/replace of the
UUIDs in the &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt; file you are not supposed to
edit. After changing the UUIDs you will boot into the new partition, and from
then on &lt;code&gt;update-grub&lt;/code&gt; seems to detect the correct UUID since it
probably just finds the UUID of the partition mounted as &lt;code&gt;/&lt;/code&gt;.

&lt;p&gt;I haven't seen this procedure written about anywhere; I just guessed that
it would work and it did. Your mileage may vary!&lt;/p&gt;

&lt;p&gt;The SSD reduced boot time a bit, but not as much as I was expecting. Down
from about 15 seconds (post-bios) to about 9. (Ubuntu did a lot of work reducing
boot times on spinning disks in the 9.x series, I think.) My bios really sucks and
takes like 20 seconds just to get to grub, so the reduction is not really noticeable.
&lt;/p&gt;

&lt;p&gt;
Boot time was a wash, but the real win is that package management
operations are much faster: running updates and starting Synaptic is no longer
unbearably slow.&lt;/p&gt;

&lt;p&gt;Overall, using a UUID to reference disks in GRUB is a win even if it does
make the procedure for rare changes like this more confusing. My old
motherboard has 2 different SATA chipsets and doesn't like some devices on some ports,
so it's nice not to have
to worry about screwing up your boot procedure when rearranging devices.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-3284727864959063259?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/3284727864959063259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/04/changing-ubuntu-lucids-boot-drive-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/3284727864959063259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/3284727864959063259'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/04/changing-ubuntu-lucids-boot-drive-with.html' title='Changing Ubuntu Lucid&apos;s Boot Drive with Grub 2'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-8922205659800025578</id><published>2011-03-29T22:19:00.002-04:00</published><updated>2011-03-29T22:24:20.570-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='storage'/><title type='text'>Cloud Storage: Expensive</title><content type='html'>&lt;p&gt;
Amazon's recently-announced &lt;a
href="https://www.amazon.com/clouddrive/learnmore"&gt;Cloud Drive&lt;/a&gt; service
shows why Internet storage still doesn't make economic sense unless you don't
have much data.
&lt;/p&gt;

&lt;p&gt;
The biggest storage tier, 1000 GB (1TB), is $1000/year. My &lt;a
href="http://log.bthomson.com/2010/03/zfs-nas-for-home-backup-on-freebsd-8.html"&gt;cheapo
FreeBSD server&lt;/a&gt; cost about $550 (plus my time) to build and stores 6000 GB
in a reasonably redundant manner. It uses about 1kWh/day of electricity and thus costs
about $26/year to operate.
&lt;/p&gt;

&lt;p&gt;
Storing your own data is more risky. Probably. If the house catches fire my
data will be destroyed. If I kick the box over while it is running, more than
2 drives will probably crash and the data will be destroyed. Then again, if
you read the terms of service for Cloud Drive, Amazon is not going to
compensate you for data loss if they screw up and delete your data, either. Maybe
they make tape backups &lt;a href="http://www.talkincloud.com/the-solution-to-the-gmail-glitch-tape-backup/"&gt;like Google does&lt;/a&gt;, maybe not. You don't really know.
&lt;/p&gt;

&lt;p&gt;
Convenience is probably better (for some folks) with a service like Cloud
Drive: you can use it with your phone or whatever though a nice interface. Me,
I have to setup ssh and deal with people trying to break in. (Then again, I can
also use my server to run IRC and host a website and do other useful work.)
&lt;/p&gt;

&lt;p&gt;
Even if you have FiOS or some ridiculous Internet connection, transfer to
local storage is probably going to be faster. I can transfer data to and from
my NAS box at gigabit speeds which makes it trivial to back up my workstation
every hour. I suspect that would be painful with a service like Cloud Drive.
&lt;/p&gt;

&lt;p&gt;
I know they are targeting mostly non-technical folks with this service. Still,
it is interesting to observe the costs from a power user's perspective.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-8922205659800025578?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/8922205659800025578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/03/cloud-storage-expensive.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8922205659800025578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8922205659800025578'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/03/cloud-storage-expensive.html' title='Cloud Storage: Expensive'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-5122841924226576275</id><published>2011-03-22T17:04:00.000-04:00</published><updated>2011-03-22T17:04:48.391-04:00</updated><title type='text'>Fawn Running Beside Car [Video]</title><content type='html'>&lt;p&gt;Took this a couple years ago...&lt;/p&gt;

&lt;iframe title="YouTube video player" width="499" height="311" src="http://www.youtube.com/embed/zQtNOx08ly0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-5122841924226576275?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/5122841924226576275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/03/fawn-running-beside-car-video.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5122841924226576275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/5122841924226576275'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/03/fawn-running-beside-car-video.html' title='Fawn Running Beside Car [Video]'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/zQtNOx08ly0/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-6672819757879909239</id><published>2011-03-11T02:15:00.000-05:00</published><updated>2011-03-11T02:15:28.044-05:00</updated><title type='text'>gmail smart labels</title><content type='html'>&lt;p&gt;Gmail's new &lt;a href="http://gmailblog.blogspot.com/2011/03/new-in-gmail-labs-smart-labels.html"&gt;smart labels&lt;/a&gt; are pretty useful. In particular the idea of having a separate box for all bulk mail. I subscribe to a lot of mailing lists so I already had a lot of filters which removed stuff from the inbox, but for some reason it had never occurred to me to detect bulk mailings and move those out of the inbox as well.&lt;/p&gt;

&lt;p&gt;With fewer things showing up in the inbox it becomes way more practical to use new mail notification.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-6672819757879909239?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/6672819757879909239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/03/gmail-smart-labels.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6672819757879909239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6672819757879909239'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/03/gmail-smart-labels.html' title='gmail smart labels'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-6444221129552835837</id><published>2011-03-03T22:48:00.000-05:00</published><updated>2011-03-03T22:48:40.910-05:00</updated><title type='text'>Yet another HTML5 canvas demo</title><content type='html'>I made a &lt;a href="http://www.bthomson.com/demos/trig_lines.html"&gt;canvas demo&lt;/a&gt; that takes advantage of the new GPU acceleration in the beta Chrome builds.

It sorta works in Firefox, too, but good god it's slow. I get 60fps at 1680x1050 in Chrome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-6444221129552835837?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/6444221129552835837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/03/yet-another-html5-canvas-demo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6444221129552835837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6444221129552835837'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/03/yet-another-html5-canvas-demo.html' title='Yet another HTML5 canvas demo'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-8998355893540546173</id><published>2011-01-21T23:58:00.000-05:00</published><updated>2011-01-21T23:58:32.062-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python: Remove Duplicate Spaces</title><content type='html'>&lt;pre class="brush:python"&gt;
&gt;&gt;&gt; from functools import partial
&gt;&gt;&gt; import re
&gt;&gt;&gt; undup_spaces = partial(re.compile(r' +').sub, ' ')
&gt;&gt;&gt; undup_spaces('  foo bar  foobar    foo bar    bar fu   ')
' foo bar foobar foo bar bar fu '
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-8998355893540546173?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/8998355893540546173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/python-remove-duplicate-spaces.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8998355893540546173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8998355893540546173'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/python-remove-duplicate-spaces.html' title='Python: Remove Duplicate Spaces'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-1389638493970448657</id><published>2011-01-17T18:26:00.001-05:00</published><updated>2011-01-22T00:00:35.981-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python itertools grouper with truncation</title><content type='html'>I wanted something like a "grouper" (see &lt;a href="http://docs.python.org/library/itertools.html"&gt;docs for itertools&lt;/a&gt;) that truncated the final list instead of filling with a fillvalue. This solution is not very efficient since the loop is in Python code and the intermediate lists must fit into memory, but it does work: 

&lt;pre class="brush:python"&gt;
def grouper(n, iterable):
  "grouper(3, 'ABCDEFG') --&gt; ABC DEF G"
  buf = []
  for i, c in enumerate(iterable):
    buf.append(c)
    if (i+1) % n == 0:
      yield buf
      buf = []
  if buf:
    yield buf
&lt;/pre&gt;

Is there a faster way to do this using the itertools primitives?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-1389638493970448657?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/1389638493970448657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/python-itertools-grouper-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1389638493970448657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/1389638493970448657'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/python-itertools-grouper-with.html' title='Python itertools grouper with truncation'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-8089997082054379931</id><published>2011-01-15T15:06:00.000-05:00</published><updated>2011-01-15T15:06:16.020-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python console prompt yes/no</title><content type='html'>I've been using the &lt;a
href="http://code.activestate.com/recipes/541096-prompt-the-user-for-confirmation/"&gt;prompt
recipe&lt;/a&gt; on Activestate for a while because I know it works, but I actually
looked at it today and realized it could be improved a bit so here you go:

&lt;pre class="brush:plain"&gt;
&gt;&gt;&gt; confirm()
Confirm n|y: 
Please enter y or n.
Confirm n|y: y
True

&gt;&gt;&gt; confirm("Detonate explosives?", allow_empty=True, default=True)
Detonate explosives? [y]|n: 
True

&gt;&gt;&gt; confirm("Invent cure for cancer?", allow_empty=True)
Invent cure for cancer? [n]|y: 
False 
&lt;/pre&gt;

&lt;pre class="brush:python"&gt;
def confirm(prompt_str="Confirm", allow_empty=False, default=False):
  fmt = (prompt_str, 'y', 'n') if default else (prompt_str, 'n', 'y')
  if allow_empty:
    prompt = '%s [%s]|%s: ' % fmt
  else:
    prompt = '%s %s|%s: ' % fmt

  while True:
    ans = raw_input(prompt).lower()

    if ans == '' and allow_empty:
      return default
    elif ans == 'y':
      return True
    elif ans == 'n':
      return False
    else:
      print 'Please enter y or n.'
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-8089997082054379931?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/8089997082054379931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/python-console-prompt-yesno.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8089997082054379931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/8089997082054379931'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/python-console-prompt-yesno.html' title='Python console prompt yes/no'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-6720121213949262012</id><published>2011-01-14T10:18:00.001-05:00</published><updated>2011-01-14T10:18:50.742-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Sandy Bridge on Linux? Nah, not yet...</title><content type='html'>&lt;p&gt;
I was looking at the new Sandy Bridge hardware yesterday. For $450 or so
I can get a CPU that's about twice as fast as my Q8200, 8G RAM, and a board with USB 3 and all the new goodies. Intel's
new P67 boards (like the BOXDP67DE) also support 32G RAM total so there's a nice
upgrade path with 2x8GB DIMMs in the future.
&lt;/p&gt;

&lt;p&gt;
Sadly they are &lt;a href="http://www.realworldtech.com/beta/forums/index.cfm?action=detail&amp;id=115458&amp;threadid=115450&amp;roomid=2"&gt;not really ready&lt;/a&gt; on linux yet unless you like compiling your own kernel.
&lt;/p&gt;

&lt;p&gt;
&lt;a
href="http://blogs.intel.com/technology/2011/01/sandybridge_on_linux_-_it_will.php?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+TechnologyIntel+(Technology%40Intel)"&gt;Intel's
comments&lt;/a&gt; are encouraging, though. Oh well, maybe in a few months.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-6720121213949262012?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/6720121213949262012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/sandy-bridge-on-linux-nah-not-yet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6720121213949262012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/6720121213949262012'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/sandy-bridge-on-linux-nah-not-yet.html' title='Sandy Bridge on Linux? Nah, not yet...'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-7847299765491536254</id><published>2011-01-11T17:39:00.001-05:00</published><updated>2011-01-11T17:45:49.588-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Quick Python zlib vs bz2 benchmark</title><content type='html'>&lt;p&gt;
I use the zlib module a lot on Google App Engine; often the tiny CPU time for
decompression is a good tradeoff to save disk space. I was curious how bz2
compares so I ran this short benchmark.
&lt;/p&gt;

&lt;p&gt;
The test file was &lt;a
href="http://www.gutenberg.org/cache/epub/4238/pg4238.txt"&gt;this plaintext
book&lt;/a&gt;, a highly-compressible source. Columns are: level, time, bytes
uncompressed, bytes compressed, ratio.
&lt;/p&gt;

&lt;pre class="brush:plain"&gt;
% ./bench.zsh

zlib compress
0   6.98ms 640599 640700 1.000
1  21.22ms 640599 274195 2.336
2  25.08ms 640599 261638 2.448
3  34.24ms 640599 249649 2.566
4  36.41ms 640599 241500 2.653
5  54.24ms 640599 232545 2.755
6  77.22ms 640599 228621 2.802
7  87.94ms 640599 228032 2.809
8 112.49ms 640599 227622 2.814
9 113.03ms 640599 227622 2.814

zlib decompress
0   1.54ms
1   6.39ms
2   6.13ms
3   6.02ms
4   6.22ms
5   5.96ms
6   5.94ms
7   5.90ms
8   5.89ms
9   5.94ms

bz2 compress
1 105.30ms 640599 196752 3.256
2 103.42ms 640599 186082 3.443
3 105.40ms 640599 180905 3.541
4 104.95ms 640599 177642 3.606
5 113.12ms 640599 176232 3.635
6 110.45ms 640599 173153 3.700
7 113.06ms 640599 169634 3.776
8 110.27ms 640599 169634 3.776
9 111.43ms 640599 169634 3.776

bz2 decompress
1  36.40ms
2  35.79ms
3  36.35ms
4  36.81ms
5  41.18ms
6  44.86ms
7  48.96ms
8  48.45ms
9  47.95ms
&lt;/pre&gt;

&lt;p&gt;
Conclusion: probably not worth it. bz2 at level=4 takes about 7 times longer
to decompress than gzip at level=9 for only a modest improvement in the
compression ratio from 2.8 to 3.6.
&lt;/p&gt;

&lt;p&gt;
Interestingly for write-heavy workloads bz2 may actually be the better choice
since compression time is not much worse than gzip at level=9.
&lt;/p&gt;

&lt;p&gt;
I think it's better not to use the timeit module for this kind of benchmark
since in typical usage you will just be compressing/decompressing some given
data once. If the operations speed up in repeat runs due to caching (and they
do), that doesn't reflect typical usage. Starting a new python process for
each test seems to reduce cache effects.
&lt;/p&gt;

&lt;p&gt;
Anyway, here is the code.
&lt;/p&gt;

&lt;pre class="brush:python"&gt;
import zlib
import bz2
import time
import sys

level = int(sys.argv[1])
mod = zlib if int(sys.argv[2]) else bz2
is_decompress = int(sys.argv[3])

with open("pg4238.txt") as f:
  data = f.read()

if is_decompress:
  c_data = mod.compress(data, level)

t = time.time()
if is_decompress:
  data = mod.decompress(c_data)
else:
  c_data = mod.compress(data, level)

print level, "%6.02fms" % (1000*(time.time() - t)),
if not is_decompress:
  print len(data), len(c_data), "%.03f" % (float(len(data))/len(c_data))
&lt;/pre&gt;

&lt;pre class="brush:shell"&gt;
#!/usr/bin/zsh
echo 'zlib compress'
for level in {0..9}; do python bench.py $level 1 0; done
echo '\nzlib decompress'
for level in {0..9}; do python bench.py $level 1 1; done
echo '\nbz2 compress'
for level in {1..9}; do python bench.py $level 0 0; done
echo '\nbz2 decompress'
for level in {1..9}; do python bench.py $level 0 1; done
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-7847299765491536254?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/7847299765491536254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/quick-python-gzip-vs-bz2-benchmark.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/7847299765491536254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/7847299765491536254'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/quick-python-gzip-vs-bz2-benchmark.html' title='Quick Python zlib vs bz2 benchmark'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-2485679227003058047</id><published>2011-01-06T02:38:00.002-05:00</published><updated>2011-01-06T02:45:46.920-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><title type='text'>GVIM: Remove Bold Font</title><content type='html'>&lt;p&gt;Found a neat function for gvim which automatically strips out bold font
directives from syntax files since there's no way to globally disable bold.
Bold really stinks on most small bitmap fonts; it is much better to use
different colors for emphasis. Add this to .gvimrc:&lt;/p&gt;

&lt;pre class="brush:plain"&gt;
function! Highlight_remove_attr(attr)
        " save selection registers
        new
        silent! put

        " get current highlight configuration
        redir @x
        silent! highlight
        redir END
        " open temp buffer
        new
        " paste in
        silent! put x

        " convert to vim syntax (from Mkcolorscheme.vim,
        "   http://vim.sourceforge.net/scripts/script.php?script_id=85)
        " delete empty,"links" and "cleared" lines
        silent! g/^$\| links \| cleared/d
        " join any lines wrapped by the highlight command output
        silent! %s/\n \+/ /
        " remove the xxx's
        silent! %s/ xxx / /
        " add highlight commands
        silent! %s/^/highlight /
        " protect spaces in some font names
        silent! %s/font=\(.*\)/font='\1'/

        " substitute bold with "NONE"
        execute 'silent! %s/' . a:attr . '\([\w,]*\)/NONE\1/geI'
        " yank entire buffer
        normal ggVG
        " copy
        silent! normal "xy
        " run
        execute @x

        " remove temp buffer
        bwipeout!

        " restore selection registers
        silent! normal ggVGy
        bwipeout!
    endfunction
    autocmd BufNewFile,BufRead * call Highlight_remove_attr("bold")
&lt;/pre&gt;

&lt;p&gt;Found &lt;a href="http://www.pixelbeat.org/settings/.gvimrc"&gt;here&lt;/a&gt;. Written
by Steve Hall.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-2485679227003058047?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/2485679227003058047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2011/01/gvim-remove-bold-font.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2485679227003058047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2485679227003058047'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2011/01/gvim-remove-bold-font.html' title='GVIM: Remove Bold Font'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-2654176220751240714</id><published>2010-12-30T16:50:00.001-05:00</published><updated>2011-01-05T22:30:32.591-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Python Kakuro Solver Now Pretty Fast</title><content type='html'>&lt;p&gt;Ahh, winter holidays. Finally got around to working on my Python &lt;a
href="https://github.com/bthomson/pykakuro"&gt;Kakuro Tools&lt;/a&gt; again. I've had
the top spot for "python kakuro" in Google for a while, but the code was
embarrassingly bad and slow. Now it is solving the fairly complex puzzle
below in less than 200ms. Not bad for an interpreted language.&lt;/p&gt;

&lt;p&gt;Still a lot of work to do before it's ready for a 1.0 release, but at least
the solving engine is pretty much done. I wonder how much slower this code is
rather than something written in a &lt;a
href="http://en.wikipedia.org/wiki/Constraint_programming"&gt;constraint
programming&lt;/a&gt; language (like the process described in &lt;a
href="http://4c.ucc.ie/~hsimonis/kakuro%20modref08.pdf"&gt;this paper&lt;/a&gt;) or a
native C implementation. C implementations can get away with using a platform
word to store the possible values for each cell which enables fast bitwise operations;
I'm sure that helps a lot. I used Python's sets which are a more generic solution
since they're not limited to 32 or 64 cell values (depending on the platform), but also
much slower.&lt;/p&gt;

&lt;pre class='brush: plain'&gt;
  0  | 0,24| 0,28|  0  | 0,14| 0,33| 0,13| 0,8 | 0,39|  0  | 0,27| 0,45| 0,16| 0,8 |  0  | 0,20| 0,32| 0,21|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 12,0|  1  |  1  |16,43|  1  |  1  |  1  |  1  |  1  | 30,0|  1  |  1  |  1  |  1  |11,10|  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 43,0|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  | 36,6|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 32,0|  1  |  1  |  1  |  1  |  1  |22,19|  1  |  1  |  1  |  1  |  1  |  1  |11,11|  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  0  |33,13|  1  |  1  |  1  |  1  |  1  |42,45|  1  |  1  |  1  |  1  |  1  |  1  |  1  |12,40|  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 15,0|  1  |  1  |  1  | 29,8|  1  |  1  |  1  |  1  |  1  |  1  |  1  |18,30|  1  |  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 11,0|  1  |  1  |  1  |  1  |24,10|  1  |  1  |  1  | 18,0|  1  |  1  |  1  |  1  |22,12|  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  0  | 0,24|34,36|  1  |  1  |  1  |  1  |  1  | 0,35|  0  |23,26|  1  |  1  |  1  |  1  |  1  | 0,21| 0,13|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 24,0|  1  |  1  |  1  |19,26|  1  |  1  |  1  |  1  | 6,6 |  1  |  1  |  1  |10,27|  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 20,0|  1  |  1  |  1  |  1  |  1  |42,27|  1  |  1  |  1  |  1  |  1  |  1  |  1  |23,28|  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 12,0|  1  |  1  | 33,7|  1  |  1  |  1  |  1  |  1  |  1  |  1  | 33,7|  1  |  1  |  1  |  1  |  1  | 0,22|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 27,0|  1  |  1  |  1  |  1  |23,12|  1  |  1  |  1  |  1  |  1  |  1  |24,12|  1  |  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 37,0|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  | 36,0|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 7,0 |  1  |  1  |  1  | 10,0|  1  |  1  |  1  |  1  | 16,0|  1  |  1  |  1  |  1  |  1  | 8,0 |  1  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
&lt;/pre&gt;

&lt;pre class='brush: plain'&gt; 
  0  | 0,24| 0,28|  0  | 0,14| 0,33| 0,13| 0,8 | 0,39|  0  | 0,27| 0,45| 0,16| 0,8 |  0  | 0,20| 0,32| 0,21|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 12,0|  7  |  5  |16,43|  1  |  3  |  4  |  2  |  6  | 30,0|  8  |  9  |  6  |  7  |11,10|  8  |  1  |  2  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 43,0|  8  |  4  |  5  |  3  |  6  |  9  |  1  |  7  | 36,6|  5  |  6  |  2  |  1  |  3  |  7  |  8  |  4  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 32,0|  9  |  8  |  6  |  2  |  7  |22,19|  5  |  4  |  2  |  3  |  7  |  1  |11,11|  2  |  5  |  3  |  1  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  0  |33,13|  6  |  7  |  8  |  9  |  3  |42,45|  9  |  3  |  6  |  8  |  7  |  5  |  4  |12,40|  9  |  3  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 15,0|  8  |  3  |  4  | 29,8|  8  |  2  |  6  |  5  |  1  |  4  |  3  |18,30|  2  |  1  |  6  |  4  |  5  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 11,0|  5  |  2  |  3  |  1  |24,10|  7  |  9  |  8  | 18,0|  1  |  5  |  9  |  3  |22,12|  9  |  7  |  6  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  0  | 0,24|34,36|  9  |  7  |  4  |  6  |  8  | 0,35|  0  |23,26|  2  |  8  |  1  |  9  |  3  | 0,21| 0,13|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 24,0|  7  |  9  |  8  |19,26|  2  |  1  |  7  |  9  | 6,6 |  2  |  1  |  3  |10,27|  3  |  1  |  2  |  4  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 20,0|  2  |  6  |  1  |  8  |  3  |42,27|  5  |  8  |  3  |  7  |  4  |  6  |  9  |23,28|  8  |  6  |  9  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 12,0|  5  |  7  | 33,7|  4  |  1  |  9  |  3  |  6  |  2  |  8  | 33,7|  4  |  8  |  9  |  7  |  5  | 0,22|
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 27,0|  6  |  8  |  4  |  9  |23,12|  8  |  2  |  3  |  1  |  5  |  4  |24,12|  1  |  8  |  2  |  4  |  9  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 37,0|  3  |  2  |  1  |  5  |  9  |  6  |  4  |  7  | 36,0|  1  |  2  |  8  |  7  |  5  |  4  |  3  |  6  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 7,0 |  1  |  4  |  2  | 10,0|  3  |  4  |  1  |  2  | 16,0|  3  |  1  |  4  |  2  |  6  | 8,0 |  1  |  7  |
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-2654176220751240714?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/2654176220751240714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2010/12/python-kakuro-solver-now-pretty-fast.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2654176220751240714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2654176220751240714'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2010/12/python-kakuro-solver-now-pretty-fast.html' title='Python Kakuro Solver Now Pretty Fast'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-373952838617082901</id><published>2010-12-29T11:15:00.001-05:00</published><updated>2011-01-05T22:08:20.521-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xmonad'/><title type='text'>Weather Alerts for XMobar</title><content type='html'>&lt;p&gt;By default &lt;a href="http://code.google.com/p/xmobar/"&gt;xmobar&lt;/a&gt;'s weather module only fetches temperature, humidity, and some other basic weather data for your location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bthomson/misc/blob/master/weather_alerts.py"&gt;This script&lt;/a&gt; fetches weather alerts (like "Winter Storm Warning") for your county in an xmobar-friendly format. Only for US users since it queries the National Weather Service.&lt;/p&gt;

&lt;p&gt;I like it for keeping track of winter weather alerts especially.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-373952838617082901?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/373952838617082901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2010/12/weather-alerts-for-xmobar.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/373952838617082901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/373952838617082901'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2010/12/weather-alerts-for-xmobar.html' title='Weather Alerts for XMobar'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-321914359641899024</id><published>2010-12-23T10:46:00.001-05:00</published><updated>2011-01-05T22:09:30.161-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZFS'/><category scheme='http://www.blogger.com/atom/ns#' term='freebsd'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Backup Strategies: Linux to FreeBSD ZFS</title><content type='html'>&lt;p&gt;
I use FreeBSD on my home server mainly for the ZFS support, but I run Linux on
my workstation and laptop.
&lt;/p&gt;

&lt;p&gt;
I've been trying to figure out the best backup strategy for this environment.
If I was running FreeBSD on my client machines and they had local ZFS
filesystems, I could use snapshots with ZFS send to propagate changes to the
server. This would be really great but is impractical until a fast, stable version of ZFS
arrives in Linux (probably never).
&lt;/p&gt;

&lt;p&gt;
For now I've settled on mounting an NFS share from the server on each machine
and then using rsync to copy changes from the local volume to the NFS share
via cron job.  Using NFS is faster than tunneling over rsync over ssh since
the server is slow. I run rsync in the mode that propagates deletions to the
destination volume and rely on zfs snapshots on the server to recover any
accidentally deleted files.
&lt;/p&gt;

&lt;p&gt;
I guess it's not perfect, but probably the best I can do without switching my
client machines to FreeBSD.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-321914359641899024?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/321914359641899024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2010/12/backup-strategies-linux-to-freebsd-zfs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/321914359641899024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/321914359641899024'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2010/12/backup-strategies-linux-to-freebsd-zfs.html' title='Backup Strategies: Linux to FreeBSD ZFS'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5265869129831265924.post-2611307882091017042</id><published>2010-12-18T22:38:00.001-05:00</published><updated>2010-12-18T22:41:02.372-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Ubuntu Slow After Hibernate Resume</title><content type='html'>&lt;p&gt;
I use hibernate probably more often than I should. It's not totally stable on
my hardware and sometimes it crashes on resume, or does weird things like
crashes on the first resume attempt but works fine on the second. And God help
you if you install some system update and then accidentally hibernate instead
of restarting. But even with all the weird idioscyncracies it's still faster
than rebooting every morning, so I use it.
&lt;/p&gt;

&lt;p&gt;I've already had to write a custom hibernate/resume script to
unmount/remount my NFS share, lest it hang on resume and make the system
unusable by locking up every shell when it tries to read my home directory
(still haven't figured out a way out of that pickle). I'm thinking about also
adding &lt;code&gt;swapoff -a; swapon -a&lt;/code&gt; to the resume script. For whatever
reason linux seems to leave everything on the swap disk by default and only page stuff
back in as it's accessed, which means the system is slow for a few hours after
hibernate resume every time you access some program you haven't accessed yet.
I rarely use even half my RAM so it makes more sense to page everything back in
right after resume so the system is snappy again.&lt;/p&gt;

&lt;p&gt;Isn't that true for most people? I wonder why this isn't done by default.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5265869129831265924-2611307882091017042?l=log.brandonthomson.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://log.brandonthomson.com/feeds/2611307882091017042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://log.brandonthomson.com/2010/12/ubuntu-slow-after-hibernate-resume.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2611307882091017042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5265869129831265924/posts/default/2611307882091017042'/><link rel='alternate' type='text/html' href='http://log.brandonthomson.com/2010/12/ubuntu-slow-after-hibernate-resume.html' title='Ubuntu Slow After Hibernate Resume'/><author><name>Brandon Thomson</name><uri>http://www.blogger.com/profile/10581002994959485431</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_HqFInTVvm5c/TEFWwhY3qKI/AAAAAAAAAUI/nCw1oKS6Ljs/S220/square-retouch.jpg'/></author><thr:total>0</thr:total></entry></feed>
