<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:sudo</id>
  <title>(it's not the colors that matter)</title>
  <subtitle>Ben Karel</subtitle>
  <author>
    <name>Ben Karel</name>
  </author>
  <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/"/>
  <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom"/>
  <updated>2009-03-11T19:58:46Z</updated>
  <lj:journal userid="524805" username="sudo" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://sudo.livejournal.com/data/atom" title="(it's not the colors that matter)"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:77331</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/77331.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=77331"/>
    <title>Moved (back) to WordPress</title>
    <published>2009-03-11T19:58:46Z</published>
    <updated>2009-03-11T19:58:46Z</updated>
    <content type="html">Since LiveJournal has been showing increasingly flashy and annoying ads, I'm moving this thing back to a hosted blog service. WordPress has a pretty nice LiveJournal importer, so I'm going to give wordpress.com a try. Whatever service I'm using will be linked to from &lt;a href="http://eschew.org/blog/"&gt;http://eschew.org/blog/&lt;/a&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:77182</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/77182.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=77182"/>
    <title>An Unexpected Side Effect of Combining C++ Features</title>
    <published>2009-03-01T05:41:00Z</published>
    <updated>2009-03-01T05:41:00Z</updated>
    <content type="html">So, a pop quiz. Suppose you write a C++ program using class B provided in a library, like so:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
#include "some-header.h"
int main() {
  B* p = new B();
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The snippet above compiles and links just fine. So the snippet below should build too, right? Mind you, the base class is not doing anything sneaky. In particular, it does not have a private destructor, or anything else designed to interfere with derivation.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
#include "some-header.h"
class D : public B {};
int main() {
  D* p = new D();
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The answer to the quiz is that this may or may not build. It will compile, but you could get unresolved symbol errors during linking. How and when, you ask? It happens when you're linking against a dynamically linked library (at least on Windows) and B has a &lt;em&gt;protected virtual&lt;/em&gt; method not exported in the DLL. The explanation (as far as I can reason) hinges on the fact that the .lib for a DLL contains only the symbols marked for export. When you're using the class directly, your compilation unit can't access the protected virtual symbol, so the linker doesn't look for it. But when you use the derived class you just defined, well, D can now access that protected virtual method in B, so the linker needs to find the method's symbol. Since the symbol is not there, boom.&lt;br /&gt;&lt;br /&gt;This situation involves no less than four distinct features coming together for the express purpose of saddening you: separate compilation, method access, inheritance, and custom symbol visibility.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:76975</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/76975.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=76975"/>
    <title>Updated Reddit Highlighter Greasemonkey Script</title>
    <published>2009-02-09T02:45:21Z</published>
    <updated>2009-02-09T02:45:21Z</updated>
    <content type="html">Quick PSA: I've updated the &lt;a href="http://eschew.org/projects/mozilla/greasemonkey/reddit-story-highlighter.user.js"&gt;Reddit Highligher Script&lt;/a&gt; to work with the changes Reddit made to their site structure a while back. I've also added highlighting stories based on linked domain name or link title, the easier to not miss anything related to Diablo III. One can never be too prepared, eh?</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:76665</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/76665.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=76665"/>
    <title>C/C++ Preprocessor Macro Idioms</title>
    <published>2009-02-05T06:14:35Z</published>
    <updated>2009-02-05T06:14:35Z</updated>
    <content type="html">I've been tormented the past few days about an article I read several years ago. I barely even remember what it was about, only that the author played very clever tricks with the preprocessor's token pasting functionality to push the limits of what the preprocessor can do. Maybe it was a &lt;a href="http://www.boost.org/doc/libs/1_37_0/libs/preprocessor/doc/ref/repeat.html"&gt;parameterized repetition macro&lt;/a&gt;? Something like that. I do remember it took advantage of the asymmetry in expansion between function-like and object-like macros.&lt;br /&gt;&lt;br /&gt;Anyways, I've been poking around the (very nice!) Chromium source code. One thing I took a close look at is how &lt;a href="http://src.chromium.org/viewvc/chrome/trunk/src/base/logging.h?view=markup&amp;amp;pathrev=8630"&gt;Google organized their logging macros&lt;/a&gt;. In the process, I noticed two tricks they used that I think are effectively preprocessor idioms, and since Google doesn't turn up much for that search phrase, I figured I'd document what I saw.&lt;br /&gt;&lt;br /&gt;The external interface of the Google logging system is pretty simple: the &lt;code&gt;LOG&lt;/code&gt; macro takes a severity parameter, such as &lt;code&gt;INFO&lt;/code&gt; or &lt;code&gt;ERROR&lt;/code&gt; and expands into a temporary object that derives from &lt;code&gt;std::ostream&lt;/code&gt;. The tricks have to do with the severities: the tokens used as severities aren't &lt;code&gt;#define&lt;/code&gt;d to the preprocessor! Instead, whatever is passed in is pasted onto a longer token that expands to an object declaration with the desired parameters. This lack of actual &lt;code&gt;#define&lt;/code&gt; statements effectively gives the severity tokens a specific local scope, even though the preprocessor deals only with explicitly global scope. And the one-to-many trick effectively forms a preprocessor-style switch() construct, where the macro parameter can affect the expansion of the rest of the macro.&lt;br /&gt;&lt;br /&gt;Incidentally, now that I look, the Boost preprocessor library uses the same switch() trick to implement &lt;a href="http://www.boost.org/doc/libs/1_37_0/libs/preprocessor/doc/ref/if.html"&gt;BOOST_PP_IF&lt;/a&gt;. Nifty.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:75530</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/75530.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=75530"/>
    <title>Patrick Awuah: Educating a new generation of African leaders</title>
    <published>2008-05-26T02:20:31Z</published>
    <updated>2008-05-26T02:20:31Z</updated>
    <content type="html">Why We Program:&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://www.ted.com/talks/view/id/156"&gt;The ability to create is the most empowering thing that can happen to an individual.&lt;/a&gt;&lt;/blockquote&gt;-- &lt;a href="http://www.ted.com/index.php/speakers/view/id/139"&gt;Patrick Awuah&lt;/a&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:75429</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/75429.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=75429"/>
    <title>The J Programming Language, also known as Oh God My Eyes Are Bleeding</title>
    <published>2008-05-05T06:16:22Z</published>
    <updated>2008-05-05T06:16:22Z</updated>
    <lj:music>Nickel Creek - House Of Tom Bombadil</lj:music>
    <content type="html">So, back towards the beginning of the semester, we had a simple assignment in Data Compression: compute pixel differences for an image file. The differences will be defined "going backwards" -- the i'th difference will be the i'th value, minus the (i-1)th value (as opposed to the (i+1)th). So, including a "virtual" pixel value of 128 at the beginning, a list of numbers such as&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;0 1 4 4 3 10&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;would be transformed into the list&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;-128 1 3 0 -1 7&lt;/kbd&gt;. Because these are really 8-bit unsigned char values, this is equivalent to &lt;kbd&gt;128 1 3 0 255 7&lt;/kbd&gt;.&lt;br /&gt;&lt;br /&gt;In a mainstream, Algol-derived language like C or Python, this problem has a simple, obvious solution that is intelligible even to programmers who don't know the language. Something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="color:#000000;background:#ffffff;"&gt;&lt;span style="color:#800000; font-weight:bold; "&gt;import&lt;/span&gt; sys

&lt;span style="color:#800000; font-weight:bold; "&gt;if&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;len&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;sys&lt;span style="color:#808030; "&gt;.&lt;/span&gt;argv&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#808030; "&gt;!&lt;/span&gt;&lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#008c00; "&gt;2&lt;/span&gt;&lt;span style="color:#808030; "&gt;:&lt;/span&gt;
    &lt;span style="color:#800000; font-weight:bold; "&gt;print&lt;/span&gt; &lt;span style="color:#0000e6; "&gt;"Error! Must give an input filename."&lt;/span&gt;
    &lt;span style="color:#800000; font-weight:bold; "&gt;print&lt;/span&gt; &lt;span style="color:#0000e6; "&gt;"\tUsage: python imgdiff.py in_file"&lt;/span&gt;
    sys&lt;span style="color:#808030; "&gt;.&lt;/span&gt;&lt;span style="color:#e34adc; "&gt;exit&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#008c00; "&gt;1&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;

infile_name &lt;span style="color:#808030; "&gt;=&lt;/span&gt; sys&lt;span style="color:#808030; "&gt;.&lt;/span&gt;argv&lt;span style="color:#808030; "&gt;[&lt;/span&gt;&lt;span style="color:#008c00; "&gt;1&lt;/span&gt;&lt;span style="color:#808030; "&gt;]&lt;/span&gt;
outfile_name &lt;span style="color:#808030; "&gt;=&lt;/span&gt; infile_name &lt;span style="color:#808030; "&gt;+&lt;/span&gt; &lt;span style="color:#0000e6; "&gt;".diff"&lt;/span&gt;


infile &lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;open&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;infile_name&lt;span style="color:#808030; "&gt;,&lt;/span&gt; &lt;span style="color:#0000e6; "&gt;"rb"&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;
data &lt;span style="color:#808030; "&gt;=&lt;/span&gt; infile&lt;span style="color:#808030; "&gt;.&lt;/span&gt;read&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#696969; "&gt;# Read all bytes from file&lt;/span&gt;
infile&lt;span style="color:#808030; "&gt;.&lt;/span&gt;close&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;

data &lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;chr&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#008c00; "&gt;128&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#808030; "&gt;+&lt;/span&gt; data &lt;span style="color:#696969; "&gt;# Prepend pseudo-pixel for diff. calculation&lt;/span&gt;

&lt;span style="color:#696969; "&gt;# Calculate the differences between each pixel in the data&lt;/span&gt;
diff_at &lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;lambda&lt;/span&gt; i&lt;span style="color:#808030; "&gt;:&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;ord&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;data&lt;span style="color:#808030; "&gt;[&lt;/span&gt;i&lt;span style="color:#808030; "&gt;]&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#808030; "&gt;-&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;ord&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;data&lt;span style="color:#808030; "&gt;[&lt;/span&gt;i&lt;span style="color:#808030; "&gt;-&lt;/span&gt;&lt;span style="color:#008c00; "&gt;1&lt;/span&gt;&lt;span style="color:#808030; "&gt;]&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;
diff &lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#808030; "&gt;[&lt;/span&gt;&lt;span style="color:#e34adc; "&gt;chr&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt; diff_at&lt;span style="color:#808030; "&gt;(&lt;/span&gt;i&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#808030; "&gt;%&lt;/span&gt; &lt;span style="color:#008c00; "&gt;256&lt;/span&gt; &lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#800000; font-weight:bold; "&gt;for&lt;/span&gt; i &lt;span style="color:#800000; font-weight:bold; "&gt;in&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;range&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#008c00; "&gt;1&lt;/span&gt;&lt;span style="color:#808030; "&gt;,&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;len&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;data&lt;span style="color:#808030; "&gt;)&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;&lt;span style="color:#808030; "&gt;]&lt;/span&gt;

outfile &lt;span style="color:#808030; "&gt;=&lt;/span&gt; &lt;span style="color:#e34adc; "&gt;open&lt;/span&gt;&lt;span style="color:#808030; "&gt;(&lt;/span&gt;outfile_name&lt;span style="color:#808030; "&gt;,&lt;/span&gt; &lt;span style="color:#0000e6; "&gt;"wb"&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;
outfile&lt;span style="color:#808030; "&gt;.&lt;/span&gt;writelines&lt;span style="color:#808030; "&gt;(&lt;/span&gt;diff&lt;span style="color:#808030; "&gt;)&lt;/span&gt; &lt;span style="color:#696969; "&gt;# Write the difference values to the output file&lt;/span&gt;
outfile&lt;span style="color:#808030; "&gt;.&lt;/span&gt;close&lt;span style="color:#808030; "&gt;(&lt;/span&gt;&lt;span style="color:#808030; "&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This Python program is short and simple. It has six blocks, half of which are just one line. For the non-programmers who might be interested in commentary (hi Joe!): The first "big" block ensures that we have an input file to read values from and a file to write to; the second block just reads the value in. The line &lt;kbd&gt;data = chr(128) + data&lt;/kbd&gt; just adds the value 128, our virtual pixel value, to the beginning of the list. The next line is a direct translation of our definition of a difference pixel, given above, into Python syntax. The trickiest line is the one defining &lt;kbd&gt;diff&lt;/kbd&gt;, because it makes use of a list comprehension. From the inside out, &lt;kbd&gt;chr( diff_at(i) % 256 )&lt;/kbd&gt; computes the i'th pixel difference, modulo 256 (which is the maximum value a character (&lt;kbd&gt;chr&lt;/kbd&gt;) can be. That computation is repeated for every pixel in the file, and the resulting list is assigned to &lt;kbd&gt;diff&lt;/kbd&gt;. Finally, the last line prints out the differences to the output file.&lt;br /&gt;&lt;br /&gt;So that's nice: simple, clean, easy, boring.  I wanted something more... esoteric.&lt;br /&gt;&lt;br /&gt;Usually, when a computer science class gets an assignment, the instructor picks the language the students use, but for this assignment, we were given free reign to pick any language we wanted to get the job done. Since this particular professor puts a lot of emphasis on program readability, I thought it would be amusing to see the expression on his face when presented with a valid solution in a completely unintelligible language. But which language to use?&lt;br /&gt;&lt;br /&gt;Perhaps the most amusing might have been a language called &lt;a href="http://en.wikipedia.org/wiki/Whitespace_(programming_language)"&gt;Whitespace&lt;/a&gt; (in which a valid solution would be a blank sheet of paper... or maybe two blank sheets of paper), but that would have been pushing it, even for me. But then I remembered reading something about J, somewhere. I thought it had been cited in an exhortation from Steve Yegge for programmers to learn a wider variety of languages, but I can't seem to find it now.&lt;br /&gt;&lt;br /&gt;So, J.&lt;br /&gt;&lt;br /&gt;Here's the equivalent program in J:&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;((256|(2-~/\])128,a.i.1!:(2}ARGV)){a.)1!:3(3}ARGV)&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;Fun, eh?&lt;br /&gt;&lt;br /&gt;Here's an easier-to-understand version:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
infile  =: 2}ARGV            NB. grab command line args
outfile =: 3}ARGV
chars   =: 1!:1 infile       NB. 1!:1 means read contents of file
nums    =: a. i. chars       NB. convert chars to ascii indices
diff    =: 2 -~/\ ]          NB. uhh...
diffs   =: 256|diff 128,nums
(diffs {a.) 1!:3 outfile
&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Okay, so that's not THAT bad for the first few lines. Sure, &lt;kbd&gt;1!:1&lt;/kbd&gt; is a pretty atrocious syntax for reading in file contents. but we can look beyond that for now. &lt;kbd&gt;a. i. chars&lt;/kbd&gt; is actually sort of cool. &lt;kbd&gt;a.&lt;/kbd&gt; is a table of the ASCII characters, &lt;kbd&gt;chars&lt;/kbd&gt; is a list of the characters from the file, and &lt;kbd&gt;i.&lt;/kbd&gt; is (in this context) the index-of operator. It works like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;kbd&gt;&lt;br /&gt;   'abcde' i. 'bed'&lt;br /&gt;1 4 3&lt;/kbd&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In essence, &lt;kbd&gt;a. i.&lt;/kbd&gt; is the J equivalent of Python's &lt;kbd&gt;ord&lt;/kbd&gt; function, but built out of a more fundamental operator. Cool enough to forgive the, er, terse syntax. But what the heck is the next line?!? &lt;kbd&gt;diff =: 2 -~/\ ]&lt;/kbd&gt;  -- are you kidding me?&lt;br /&gt;&lt;br /&gt;Actually, it's straight out of &lt;a href="http://jsoftware.com/help/dictionary/d430.htm"&gt;the J vocabulary reference&lt;/a&gt;. Sentences in J read right-to-left. The &lt;kbd&gt;]&lt;/kbd&gt; is an identity operator; it simply selects whatever comes to its right. In essence, here it stands in for the thing being diffed, much like the word "it" itself. The &lt;kbd&gt;\&lt;/kbd&gt; character means &lt;a href="http://jsoftware.com/help/dictionary/d430.htm"&gt;infix&lt;/a&gt;, where x is 2, u is &lt;kbd&gt;-~/&lt;/kbd&gt;, and y is &lt;kbd&gt;]&lt;/kbd&gt;. I'll cover u in a second, but first, a quick illustration of &lt;kbd&gt;\&lt;/kbd&gt;. Suppose you wanted to select every successive pair of elements from the list 1 2 3 4. Then u would simply be the identity function ], like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;kbd&gt;   2 ] \ 1 2 3 4&lt;br /&gt;1 2&lt;br /&gt;2 3&lt;br /&gt;3 4&lt;/kbd&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So what does &lt;kbd&gt;-~/&lt;/kbd&gt; mean? &lt;kbd&gt;-&lt;/kbd&gt; is the subtraction operator, simple enough. &lt;kbd&gt;/&lt;/kbd&gt; is the insert operator, so +/ 1 2 3 is 1+2+3, and -/ 1 2 is 1 - 2. But note that we don't want 1 - 2, we want 2 - 1. That's what &lt;kbd&gt;~&lt;/kbd&gt; does -- it swaps arguments, so 1 -~ 2 is the same as 2 - 1. Phew!&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;256|&lt;/kbd&gt; means compute values mod 256. &lt;kbd&gt; { a. &lt;/kbd&gt; is the equivalent of the &lt;kbd&gt;chr&lt;/kbd&gt; function in Python, converting integers back to characters. And, finally, &lt;kbd&gt;1!:3&lt;/kbd&gt; prints.&lt;br /&gt;&lt;br /&gt;Simple and intuitive, eh?&lt;br /&gt;&lt;br /&gt;Here's another example. The task is to take a binary file and figure out the Huffman codewords encoded therein.  The file format is 256 words of 4 bytes, followed by 256 sets of 1-byte lengths. Each length gives how many of the low-order bits from the corresponding word are part of the Huffman codeword.&lt;br /&gt;&lt;br /&gt;Python, I was pleased to see, has a module called struct that is built for doing exactly this kind of bit-level interpretation. Given a string of 4 chars, the value of those chars as an integer can be had with struct.unpack("l", chars). Cool! Unfortunately, Python doesn't have built-in libraries for converting integers to binary strings. The end program ended up being about 25 lines, not including trivial things like file input.&lt;br /&gt;&lt;br /&gt;J fares rather better. Negative numbers passed to the infix operator gives non-overlapping infixes, perfect for splitting our list of bytes into chunks of 4. &lt;br /&gt;&lt;blockquote&gt;&lt;kbd&gt;   _3 ]\ 'abcdefghi'&lt;br /&gt;abc&lt;br /&gt;def&lt;br /&gt;ghi&lt;/kbd&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And J has built-in operators for converting to and from binary representation of integers. So, given a list of four integers, we can select the low, oh, four bits like this:&lt;br /&gt;&lt;kbd&gt;&lt;blockquote&gt;   (-4) {. , #: 0 0 0 9&lt;br /&gt;1 0 0 1&lt;/blockquote&gt;&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;That really speaks to the conciseness of J, I think. From 25 lines of Python to one line of J.&lt;br /&gt;&lt;br /&gt;J is like concentrated Perl, with all the sugar evaporated out. Honestly, it makes my brain hurt to look at J for too long.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:75255</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/75255.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=75255"/>
    <title>Summer of Code 2008 Projects</title>
    <published>2008-04-24T21:56:03Z</published>
    <updated>2008-04-24T21:56:03Z</updated>
    <content type="html">So, the Summer of Code 2008 projects were posted a few days ago.&lt;br /&gt;&lt;br /&gt;A few of the ones I think are particularly interesting:&lt;br /&gt;&lt;br /&gt;PHP: &lt;a href="http://code.google.com/soc/2008/php/appinfo.html?csaid=73D5F5E282F9163F"&gt;Zend LLVM Extension&lt;/a&gt;&lt;br /&gt;Vim: &lt;a href="http://code.google.com/soc/2008/vim/appinfo.html?csaid=CC648339762A7BB9"&gt;On-the-fly Code Checker&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/vim/appinfo.html?csaid=6450771E3BC08877"&gt;Visual Studio 2005/2008 Plugin&lt;/a&gt;&lt;br /&gt;Python: &lt;a href="http://code.google.com/soc/2008/psf/appinfo.html?csaid=DA6AC3DE94E157E"&gt;Django on the JVM&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/soc/2008/hg/about.html"&gt;Mercurial&lt;/a&gt;: &lt;a href="http://code.google.com/soc/2008/hg/appinfo.html?csaid=EC7D811E53CA98EF"&gt;Rebasing&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/hg/appinfo.html?csaid=2757CDDD2156F1A7"&gt;svn tools&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/hg/appinfo.html?csaid=B091D9B819911D09"&gt;partial cloning&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/hg/appinfo.html?csaid=746BEC7D9EF35A79"&gt;TortoiseHG for Linux&lt;/a&gt;&lt;br /&gt;LLVM: &lt;a href="http://code.google.com/soc/2008/llvm/appinfo.html?csaid=51287D6B3C6C9E62"&gt;C++ classes support&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/llvm/appinfo.html?csaid=FE11FE99D22CA677"&gt;llvm/clang distcc&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/llvm/appinfo.html?csaid=1781294C0159DD2"&gt;STM support&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/soc/2008/gcc/about.html"&gt;GCC&lt;/a&gt;: &lt;a href="http://code.google.com/soc/2008/gcc/appinfo.html?csaid=E9374E6D3D6980BB"&gt;Windows Improvements&lt;/a&gt;, &lt;a href="http://code.google.com/soc/2008/gcc/appinfo.html?csaid=8804D57CC237C5EE"&gt;C++0x lambda functions&lt;/a&gt; &lt;br /&gt;&lt;a href="http://code.google.com/soc/2008/boost/about.html"&gt;Boost&lt;/a&gt;: &lt;a href="http://code.google.com/soc/2008/boost/appinfo.html?csaid=902E3C97E6715F39"&gt;Multi-core/SIMD optimizations for Boost::Math and Boost::Graph&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/soc/2008/cairo/about.html"&gt;Cairo&lt;/a&gt;: &lt;a href="http://code.google.com/soc/2008/cairo/appinfo.html?csaid=148ACAAD96F63E91"&gt;HDR image surface type&lt;/a&gt;&lt;br /&gt;Portland State University: &lt;a href="http://code.google.com/soc/2008/psu/appinfo.html?csaid=DAECFBB3EA45C2AB"&gt;A System for Patent Categorization and Analysis&lt;/a&gt;, &lt;br /&gt;X.Org: &lt;a href="http://code.google.com/soc/2008/xorg/appinfo.html?csaid=ACD6AA025594454A"&gt;GPU-Accelerated Video Decoding&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Other thoughts: Gosh, &lt;a href="http://code.google.com/soc/2008/psf/about.html"&gt;Python&lt;/a&gt; and &lt;a href="http://code.google.com/soc/2008/kde/about.html"&gt;KDE&lt;/a&gt; have a lot of projects! Looks like Cython and NumPy are popular Python subprojects. Mercurial is four for four in terms of interesting-to-me projects. Five of eight Linux projects are printing-related.&lt;br /&gt;&lt;br /&gt;Good luck to everyone working on it this year!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:74785</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/74785.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=74785"/>
    <title>Going offline</title>
    <published>2008-03-28T07:30:53Z</published>
    <updated>2008-03-28T07:30:53Z</updated>
    <content type="html">In 10 hours, I'll be going across the country for a few days to see my brother and take advantage of the ridiculous amount of snow Oregon has been getting. After that, I'll be home for a few days, and then off to Canada for the &lt;a href="http://icpc.baylor.edu/icpc/finals/"&gt;ACM Programming Contest&lt;/a&gt;. I'll be back April 10.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:74681</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/74681.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=74681"/>
    <title>Debbie Downer Injects Reality</title>
    <published>2008-03-02T02:48:16Z</published>
    <updated>2008-03-02T02:48:16Z</updated>
    <lj:music>Show Me - John Legend</lj:music>
    <content type="html">&lt;a href="http://en.wikipedia.org/wiki/List_of_school_related_attacks"&gt;According to Wikipedia&lt;/a&gt;, in the last ten years, approximately 96 people have been killed and 94 wounded by school shootings.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://factfinder.census.gov/servlet/QTTable?_bm=y&amp;amp;-geo_id=01000US&amp;amp;-qr_name=DEC_2000_SF3_U_DP2&amp;amp;-ds_name=DEC_2000_SF3_U&amp;amp;-_lang=en&amp;amp;-redoLog=false&amp;amp;-_sse=on"&gt;census in 2000&lt;/a&gt; showed a total of 33.86 million students at the high school level or above. That gives (190/10)/(33.86e6/1e5), which works out to a rate of approximately .056 per 100000 students being killed or injured per year.&lt;br /&gt;&lt;br /&gt;Incidentally, that's a little less than the rate given by the NIH for accidental alcohol poisoning deaths in 1996-1998 in the 15-24 age group. &lt;a href="http://pubs.niaaa.nih.gov/publications/arh27-1/110-120.htm"&gt;Extrapolating from NIH data&lt;/a&gt;, this means that, on average, 20.22 students die directly from alcohol poisoning, and 64 die directly or indirectly of alcohol poisoning. In addition, according to &lt;a href="http://www.collegedrinkingprevention.gov/NIAAACollegeMaterials/magandprev.aspx"&gt;researchers at Boston University&lt;/a&gt;, among college students in 2001, there were 1349 alcohol-related motor vehicle crash deaths, plus an additional 368 nontraffic alcohol-related injury deaths.&lt;br /&gt;&lt;br /&gt;So, as a student, I am statistically more likely to drink myself to death than to be shot by another student. And I'm 140 times more likely to be killed by drunk driving than a school shooting.&lt;br /&gt;&lt;br /&gt;But still. University police officers will be walking around with guns. To make us safer, I'm told. If only they could save us from ourselves.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:73891</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/73891.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=73891"/>
    <title>Funky Math</title>
    <published>2008-02-15T01:45:51Z</published>
    <updated>2008-02-15T01:51:36Z</updated>
    <content type="html">My sister and I have been independently growing more cognizant of money. One interesting finance site is &lt;a href="http://www.mint.com/"&gt;Mint&lt;/a&gt;. It looks very convenient, but I feel more than a little squeamish about putting my financial information in a third party website.&lt;br /&gt;&lt;br /&gt;Mint also has &lt;a href="http://blog.mint.com/blog/"&gt;a blog that's chock-full of useful tips&lt;/a&gt;. In one post, they give &lt;a href="http://blog.mint.com/blog/finance-core/a-young-professionals-car-buying-guide/"&gt;a quick overview of the practical financial aspects of car-buying&lt;/a&gt;. One thing that caused me to raise an eyebrow, however, was their stance on down payments. In essence, they noted that paying a higher monthly interest rate and while keeping a "down payment" in a high-yield savings account can be better than using the down payment to decrease the size of your car loan. That's pretty unintuitive! They're saying that taking an extra $4,000 worth of car-payment-loan at 7.5% and putting $4000 in a savings account at 4.75% is BETTER the alternative, which is using that four thousand in the lower-rate account to "pay off" the higher-interest-rate loan. That doesn't make sense at first glance; usually, you're best off when you pay off loans in decreasing order of interest rates.&lt;br /&gt;&lt;br /&gt;I checked their math; sure enough, you're better off taking the larger loan. Strange! I realized a few days later, while their comparison is useful and reflects what goes on in "the real world," it's not entirely apples to apples. The reason lies not only in how much money is loaned, paid, and invested, but also &lt;strong&gt;when&lt;/strong&gt;. Also, as an aside: In calculating interest on money you invest, Mint assumed no compounding. I redid the numbers to be a little more realistic, compounding once a month.&lt;br /&gt;&lt;br /&gt;As a quick overview: In both cases the car is $20,000, and you have a 48-month repayment plan at 7.5%. &lt;br /&gt;&lt;br /&gt;In case 1, you pay $4,000 down and pay $387 a month. $4,000 + 48 * $387 = $22,576. &lt;br /&gt;&lt;br /&gt;In case 2, you pay nothing down, and your monthly payment is $484, and the total amount you pay at the end is $23,232, $656 more than case 1. At this point, it looks like the down payment is a good idea: you pay less money! But if you take the down payment and put it in a CD at 4.75% APY, you'll earn $835, and will come out $179 richer than case 1.&lt;br /&gt;&lt;br /&gt;So what gives?&lt;br /&gt;&lt;br /&gt;Well, the thing is that &lt;em&gt;case 2 assumes you have more money to start with&lt;/em&gt;.  If you simply took a down payment, the most money you've ever invested in the car at any given point in time is &lt;b&gt;$22,576&lt;/b&gt;, on the day you send in your last car payment. In contrast, look what happens in case 2. Your car payments total $23,232, PLUS you have to pay an ADDITIONAL $4,000 to earn interest in the CD. That means that right after you send in the last car payment, and before you close out the CD, you are &lt;b&gt;$27,232&lt;/b&gt; poorer than the day you signed the loan. After you close the CD, of course, your total cost comes out to a final value of $22,472.&lt;br /&gt;&lt;br /&gt;So, then, what's the apples-to-apples comparison? You need to give yourself 27,232 - 22,576 = $4,656 more to invest over the course of the 48 months. That way, when you're done with the payments in case 1, you'll have set aside exactly as much money in total as you did in case 2. Coincidentally enough (just kidding!), $4,656/48 comes out to &lt;i&gt;$97 per month, which is the exact difference&lt;/i&gt; between the monthly payments in the two scenarios!&lt;br /&gt;&lt;br /&gt;This makes sense: now, in both cases, we have an initial outlay of $4,000 that we use for something-or-other, and monthly payments of $484. For our "new" case 1, we use $4,000 for a down payment, and invest the extra $97 per month this frees up. Assuming we our only use of the extra money is to make deposits into our CD or savings account, we will earn $598 interest on our principal of $4,656. This is excellent: we earn less interest, but we also pay much less interest, and our total cost is a mere $21,978. Instead of being $179 richer than we were originally, we're now $598 richer. &lt;b&gt;&lt;i&gt;Yay!&lt;/i&gt;&lt;/b&gt; For completeness, I'd also note that this is essentially the same ($8 less) than if we could avoid paying for the higher-interest-rate car loan by both making a down payment AND giving the higher monthly payment over a smaller number of months.&lt;br /&gt;&lt;br /&gt;What can we conclude? &lt;strong&gt;The best strategy is to make as large a down payment as possible at the beginning, and then, each month, put as much leftover money as we can into a high-yield savings account.&lt;/strong&gt; Shocking, isn't it?&lt;br /&gt;&lt;br /&gt;As an aside, the economic cost of the car itself (ignoring practical things like title fees and insurance, as well as the monkey wrench known as inflation) is not $20,000, nor is it $21,978. The future value of the money used to pay for the car is &lt;b&gt;$30,466&lt;/b&gt;. That's how much you could have had if you didn't buy the car in the first place. This means that the opportunity cost of the car is more than 150% of the sticker price!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:73478</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/73478.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=73478"/>
    <title>Review: Founders at Work</title>
    <published>2008-02-06T03:47:10Z</published>
    <updated>2008-02-06T03:49:08Z</updated>
    <category term="review"/>
    <content type="html">&lt;h3&gt;Founders at Work: Stories of Startups' Early Days&lt;/h3&gt;&lt;br /&gt;Oops, I got sidetracked. I'd been talking about startups, and then I got distracted by the "ooh shiny" of speech recognition and ACM problems. I'm not actually done with speech recognition quite yet, but this book was in my queue first. Yeah, no more procrastinating for me! It doesn't have anything to do with the fact that&amp;nbsp;the book is due back at the library in a few hours! No sirree Bob!&lt;br /&gt;&lt;br /&gt;Founders at Work is&amp;nbsp;a collection of thirty-two interviews with the founders of successful technology companies. For anyone interested in tech, tech history, or behind-the-scenes glimpses of startup life, the book offers hundreds of pages of insight, trivia, lessons learned, and advice.&lt;br /&gt;&lt;br /&gt;A number of things stand out about the stories, common threads shared between stories. One is that the majority of the companies took a very roundabout path towards success.&amp;nbsp;Many companies started with a business plan that got thrown&amp;nbsp;out at the first available opportunity. Many others started with no real business plan at all.&amp;nbsp;The photo-sharing site Flickr was originally created by Ludicorp&amp;nbsp;to be part of an online game, and didn't appear until two years after Ludicorp itself was started. PayPal started&amp;nbsp;doing cryptography software for Palm Pilots. They did&amp;nbsp;a website for one of their products as an afterthought;&amp;nbsp;that website quickly defined the company.&amp;nbsp;Pyra Labs, creators of Blogger, was started by friends&amp;nbsp;before they had&amp;nbsp;any product&amp;nbsp;ideas. They eventually focused on building an ambitious collaboration tool called Pyra, and kept each other updated with a&amp;nbsp;dirt-simple blogging system. In retrospect, of course, it's obvious:&amp;nbsp;it was that&amp;nbsp;blogging system, not Pyra, that solved a real&amp;nbsp;problem in a useful way.&amp;nbsp;Quite a few other products started off with one or two people scratching a personal itch. Bloglines, del.icio.us, Firefox, and Yahoo all started out as humble&amp;nbsp;tools meant for nobody but their creators. &lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Only a few -- WebTV,&amp;nbsp;Software&amp;nbsp;Arts, Research In Motion, Shareholder.com, plus maybe Excite and Six&amp;nbsp;Apart&amp;nbsp;-- became successful by the "straight-and-narrow" approach. And of those, note the most are (or were) hardware companies in some form or another. &lt;a href="http://en.wikipedia.org/wiki/Mike_Lazaridis"&gt;Mike Lazaridis&lt;/a&gt;, for example, started RIM when he was in his senior year of college, and dropped his coursework when he was just a month away from graduating!&lt;br /&gt;&lt;br /&gt;WebTV&amp;nbsp;was, in some ways, the most conventional story, or at least the one that most closely matches the prototypical Silicon Valley startup&amp;nbsp;mythos. A hacker (&lt;a href="http://en.wikipedia.org/wiki/Steve_Perlman"&gt;Steve Perlman&lt;/a&gt;) is messing around and comes up with a cool hack&amp;nbsp;-- high-res computer graphics on a TV! Steve shows a friend, they start a company, get funding, and get acquired by Microsoft two years later for hundreds of millions of dollars. &lt;br /&gt;&lt;br /&gt;TiVo straddles the fence a bit. They started off with a grandiose business plan involving home networks, servers, and backups. &lt;a href="http://iinnovate.blogspot.com/2006/09/mike-ramsay-co-founder-of-tivo.html"&gt;Mike Ramsay&lt;/a&gt;, one of the co-founders, called it "flamboyant." Before long they realized that their original vision was too far-reaching, and scaled their scope down a bit. Wisely, they focused on doing one thing, DVR, and doing it well.&lt;br /&gt;&lt;br /&gt;One other thing about TiVo is how it was started. Like several other companies, including Marimba,&amp;nbsp;TiVo was originally just two guys, Mike Ramsay and &lt;a href="http://www.forbes.com/finance/mktguideapps/personinfo/FromMktGuideIdPersonTearsheet.jhtml?passedMktGuideId=1021759"&gt;Jim Barton&lt;/a&gt;, with no concrete ideas. They&amp;nbsp;just had a solid belief in each other and themselves. In Mike's own words, "It would be kind of fun to work together on some ideas, because we come at it from different angles. Maybe we'll come up with something. Maybe we could do a company."&lt;br /&gt;&lt;br /&gt;Other interesting bits from the book, in no particular order:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Thanks to &lt;a href="http://blog.redfin.com/"&gt;Glenn Kelman&lt;/a&gt;'s talk, I guessed correctly that Sabeer Bhatia, co-founder of Hotmail, went to Stanford! Though he was there for his M.S., not a B.S. Anyways, here's Bhatia's account of his initial negotiations with Microsoft: "They gave a presentation about how much they liked the company and this and that, and they said they wanted to buy us and placed an offer of $160 million. I knew that that was the opening shot and I said "Thank you very much for making an offer. We really, really like your company and like the fact that you like us so much. We'll go back to our board and discuss this and get back to you."" &lt;a href="http://sudo.livejournal.com/72085.html"&gt;Sounds mighty familiar&lt;/a&gt;, after &lt;a href="http://norfolk.cs.washington.edu/htbin-post/unrestricted/colloq/details.cgi?id=654"&gt;hearing Glenn's talk&lt;/a&gt;! &lt;/li&gt;&lt;br /&gt;&lt;li&gt;According to &lt;a href="http://en.wikipedia.org/wiki/Steve_Wozniak"&gt;Steve Wozniak&lt;/a&gt;, little real work on the early Apple computers got done in the famous garage. Engineering work happened in Woz's cubicle at HP and his Cupertino apartment, not the garage. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Lesson learned from Excite: "Hire slowly and carefully," and be "cheap, cheap, cheap." &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Yahoo started taking off when the original co-founders, Jerry Yang and David Filo, were graduate students at Stanford. &lt;a href="http://books.google.com/books?id=oFTYD9IHX5YC&amp;amp;pg=PT134&amp;amp;lpg=PT134&amp;amp;ots=MKFulK8Oqj&amp;amp;sig=6p2Sct0_FDiV-hQo_GGvNHEILJw#PPT134,M1"&gt;Quoth&lt;/a&gt;&amp;nbsp;&lt;a href="http://www.questbridge.org/about/staff.html"&gt;Tim Brady&lt;/a&gt;, Yahoo's first non-founding employee: "... And all of a sudden both of them went from doing their graduate work to adding websites to their list for 8 hours a day. As chance would have it, their thesis advisor was on sabbatical, so there was really no one looking after them, so it all worked. Had their advisor been there, it might not have happened." &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Marimba, 1999. Post IPO, morale is low, people are leaving. One of the co-founders, &lt;a href="http://www.artfahrt.com/personal/resume-april-2005.html"&gt;Arthur van Hoff,&lt;/a&gt; wants to buy an espresso machine. "No," he's told, that's wasting company money. Eventually, another guy quits, and van Hoff gets fed up. He and a friend buy the machine with their own money. The CFO, when&amp;nbsp;he learned of&amp;nbsp;this fifteen-thousand dollar espresso machine bought against his wishes, "almost had a baby." Needless to say, a passing month proved van Hoff right.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://paulbuchheit.blogspot.com/"&gt;Paul Buchheit&lt;/a&gt;, who created the first prototype of &lt;a href="http://mail.google.com/"&gt;Gmail&lt;/a&gt;, has an interesting thought experiment: How much would it take to get you to play Russian roulette if the gun had a billion barrels? "A lot of people [...] they'd say "I wouldn't do it at any price." But, of course, we do that every day. They drive to work in cars to earn money and they are taking risks all the time, but they don't like to acknowledge that they are taking risks. &lt;a href="http://www.rgemonitor.com/blog/roubini/220816"&gt;They want to pretend that everything is risk-free&lt;/a&gt;."&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:73307</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/73307.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=73307"/>
    <title>ACM Programming Contest solution walkthrough</title>
    <published>2008-01-28T20:33:36Z</published>
    <updated>2008-01-28T21:19:12Z</updated>
    <category term="acm code"/>
    <content type="html">In preparation for the ACM World Finals coming up in April, we've been running through previous years' problem sets to get a feel for what we'll be up against. It's been interesting, for the most part. The problems definitely require more up-front thought before a solution presents itself, compared to the "regular" contest problems. Since a cursory Google search didn't turn up anything useful for "ACM contest walkthrough," I thought I'd write up the solution to one of the more interesting problems we've covered.&lt;br /&gt;&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The problem at hand comes from the &lt;a href="http://icpc.baylor.edu/past/icpc2005/Finals/Problems.pdf"&gt;2005 ACM World Finals problem set&lt;/a&gt;. Problem B, "Simplified GSM Network," is the one we're interested in.&lt;br /&gt;&lt;br /&gt;Here's an image that illustrates the sample input for the problem:&lt;br /&gt;&lt;img src="http://eschew.org/mirror/acm/gsm-diagram.png" width="428" height="408" title="GSM Diagram"&gt;&lt;br /&gt;&lt;br /&gt;The problem includes a bunch of irrelevant verbiage meant to slow down contestants as they try to figure out what's important and what isn't. Input consists of a set of (x,y) coordinates for the towers and italic-numbered cities, plus a list of (city, city) pairs specifying which cities are connected by roads. Finally, another list of (city A,city B) pairs is given, which this time are start and end cities that (might) be connected. Output is the minimum number of cell boundaries a traveler would cross in going from A to B. In the picture above, those numbers (which I'll refer to as &lt;em&gt;weights&lt;/em&gt;) are colored red.&lt;br /&gt;&lt;br /&gt;One noteworthy feature of the sample input is that the cell towers fall on a nice, neat grid pattern. This makes determining the number of cell crossings easy: for x and y coords, just take the difference of the floor() values. In code, this would be something like&lt;br /&gt;&lt;code&gt;abs(floor(x1) - floor(x2))   abs(floor(y1) - floor(y2))&lt;/code&gt;, assuming that the given cities are located at (x1,y1) and (x2,y2).&lt;br /&gt;&lt;br /&gt;&lt;img src="http://eschew.org/images/mirror/ackbar.jpg" width="288" height="374" title="" style="float: right;"&gt; Heed Admiral Ackbar's warning! Nothing in the problem specification constrains the locations of the cell towers.  That means that sure as the sun is going to rise tomorrow, those towers are going to be in all sorts of crazy places. That, in turns, means we need to think harder about how we're going to figure out how many cell boundaries a given road crosses.&lt;br /&gt;&lt;br /&gt;My first idea involved doing things roughly the way someone doing it by hand would -- construct cell boundaries by starting with small line segments through the perpendicular bisectors of all the lines connecting adjacent cities, and extend until they touch. Unfortunately, that's complex and error-prone for any but the simplest arrangements of cell towers. Dr. Saunders was the first to have the key insight: every point is in the cell of the closest tower. He drew something on the whiteboard that looked like this:&lt;br /&gt;&lt;img src="http://eschew.org/mirror/acm/gsm-pentagon.png" width="400" height="380" title="GSM Pentagon"&gt;&lt;br /&gt;&lt;br /&gt;The black dots represent towers; the green line a road. So for every tower (A / D), there's a point on the road closest to that tower (&lt;i&gt;q3 / q2&lt;/i&gt;), where the teal and green lines meet.  And for every such point &lt;i&gt;q&lt;/i&gt;,  there is, in turn, a (possibly different) tower closest to &lt;i&gt;q&lt;/i&gt;. In the image above, there are three red dots, marking the three cell boundaries the green road crosses. And there are a total of four towers that are closest to at least one of the five &lt;i&gt;q&lt;/i&gt; points. So, take the cardinality of the set of closest-towers and subtract one, and that is the number of cell boundaries crossed.&lt;br /&gt;&lt;br /&gt;If that's not clear, it may make more sense (at least it does to me) if you work the logic out backwards. The number of cell boundaries crossed is one less than the number of cells the road travels through. So how many cells does the road travel through? Well, if the road travels through tower A's cell, there must be &lt;em&gt;some point&lt;/em&gt; on the road that is closer to tower A than any other tower, because that's a requirement for any point being inside a tower's cell. So, we take the &lt;b&gt;n&lt;/b&gt; points on the road closest to the &lt;b&gt;n&lt;/b&gt; towers, and then the set of towers closest to those &lt;b&gt;n&lt;/b&gt; points. That gives us the set of cells the road passes through.&lt;br /&gt;&lt;br /&gt;OK, so now we can figure out the weights for each road, at least in theory. That's all well and good. The next step is to figure out how we get between cities in the minimum number of cell-boundary crossings. This screams graph theory: our cities are nodes, our roads edges. Computer scientists call this the &lt;a href="http://en.wikipedia.org/wiki/Shortest_path_problem"&gt;shortest path problem&lt;/a&gt;, and there are a variety of algorithms to solve it. As it turns out, there's no known algorithm in existence that will &lt;em&gt;only&lt;/em&gt; give the shortest path between two nodes (cities). You can't find out the shortest path from A to B without also discovering, along the way, shortest paths from A to every other node in addition to B. If &lt;a href="http://en.wikipedia.org/wiki/Adversary_(online_algorithm)"&gt;your algorithm doesn't know&lt;/a&gt; all the shortest paths starting at A, it's possible that one of those other paths could lead to a better answer.&lt;br /&gt;&lt;br /&gt;Because we could be looking for shortest paths between any pair of nodes, and because our &lt;a href="http://en.wikipedia.org/wiki/Graph_theory"&gt;graph&lt;/a&gt; isn't too big, we'll use a very cool algorithm called &lt;a href="http://en.wikipedia.org/wiki/Floyd-Warshall_algorithm"&gt;Floyd-Warshall&lt;/a&gt; to find the shortest path between every pair of cities.&lt;br /&gt;&lt;br /&gt;Floyd-Warshall is clever, concise, and easily parallelizable. I love it. The core of the algorithm is this: suppose you have nodes labeled 1 to &lt;i&gt;n&lt;/i&gt;. And suppose you know the shortest path between nodes i and j, such that the path only involves nodes labeled with numbers smaller than k.&lt;br /&gt;&lt;img src="http://eschew.org/mirror/acm/floyd.png" width="400" height="300" title="Floyd&amp;#39;s Algorithm illustration"&gt;&lt;br /&gt;Then if you allow the path to include node k, there are two choices: either the path you already have is shorter, or the shorter path is now the path connecting nodes i and k, plus the path connecting k and j.&lt;br /&gt;&lt;br /&gt;This can be expressed as a remarkably simple and elegant way, with three nested loops:&lt;pre&gt;          for(int k = 0; k &amp;lt; n;   k) {
                for(int i = 0; i &amp;lt; n;   i) {
                    for(int j = 0; j &amp;lt; n;   j) {
                        spath[edge(i,j)] = min(
                                spath[edge(i,j)],
                                spath[edge(i,k)]   spath[edge(k,j)]);
                    }
                }
           }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Back to the problem at hand. What we have, from a high level, should work. Compute weights by taking each road, then computing the closest point on the road to each tower, and then the closest tower to each of those points. Take the set of those closest towers, and the weight for the road is one less than the set's cardinality. Then, after all the weights have been calculated, use those weights as part of Floyd's algorithm, which gives us what we want: a shortest-path value for the start/destination city pairs. &lt;br /&gt;&lt;br /&gt;There's one problem left, though. I glossed over a pretty major portion of the actual program. Namely, how does that geometry stuff actually work in code? There are no pretty pictures drawn inside the program. We get numbers in, crunch 'em, and out come results. &lt;br /&gt;&lt;br /&gt;This is one of the bits I think is the coolest. Toy classes like Point are usually one of the first examples given by books trying to teach Object-Oriented programming. But the ACM contest isn't about OO masturbation. Time spent typing out a Point class implementation is time NOT spent solving the actual problem at hand. Thus, I present to you the best-kept secret of the STL for programming contests: the &lt;tt&gt;complex&lt;/tt&gt; class.&lt;br /&gt;&lt;br /&gt;It's technically meant for representing values on the complex plane, but if we sweep the imaginary constant under the rug, we've got a handy-dandy general representation of points on a 2D Cartesian plane. Best of all, the STL gives us, for free, a bunch of methods that have geometrical meaning, including vector addition and subtraction! The key idea here is an equivalence between points and vectors. A point (x,y) is equivalent to the (x,y) position vector -- that is, a vector from (0,0) to (x,y). Any given vector, or line segment, can be represented with a pair of complex numbers: the location of the tail of the vector, and the other is the vector's direction and length.&lt;br /&gt;&lt;br /&gt;If we have points such as &lt;tt&gt;p = (4,5)&lt;/tt&gt; and &lt;tt&gt;q = (1,1)&lt;/tt&gt;, the STL gives us length and angle for free: &lt;tt&gt;abs(q) == sqrt(2)&lt;/tt&gt; and &lt;tt&gt;arg(q) == 0.785398&lt;/tt&gt;, which is &lt;a href="http://www.google.com/search?q=45 degrees in radians"&gt;45 degrees in radians&lt;/a&gt;. Plus, if we want the distance between p and q, it's simply &lt;tt&gt;abs(p - q)&lt;/tt&gt; which is of course 5. But the fun's only getting started! What we really want is some elementary linear algebra.&lt;br /&gt;&lt;br /&gt;We'll start with the dot product. The &lt;a href="http://en.wikipedia.org/wiki/Dot_product"&gt;dot product&lt;/a&gt; of (a,b) and (c,d) is defined as (ac   bd). &lt;a href="http://mathworld.wolfram.com/ComplexMultiplication.html"&gt;Multiplying complex numbers&lt;/a&gt; (a   &lt;i&gt;i&lt;/i&gt;b) * (c   &lt;i&gt;i&lt;/i&gt;d) yields (ac - bd)   &lt;i&gt;i&lt;/i&gt;(ad   bc). Note that the real part is almost what we want, but the sign of the second part is wrong. So, we merely multiply by the &lt;a href="http://en.wikipedia.org/wiki/Complex_conjugate"&gt;complex conjugate&lt;/a&gt;, and take the real portion of the result. And behold: dot product of 2D vectors in one line of code!&lt;br /&gt;&lt;tt&gt;double   dot(P a, P b) { return  real(a*conj(b)); }&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;P is just shorthand for an STL complex point. Anyways, dot products are nice, but what they REALLY let us do is take &lt;a href="http://en.wikipedia.org/wiki/Projection_(linear_algebra)"&gt;projections&lt;/a&gt;. The Wikipedia page is quite indecipherable and gives no outstanding indication of how tremendously useful projections are to us. The &lt;a href="http://mathworld.wolfram.com/Projection.html"&gt;MathWorld page for projections&lt;/a&gt; is slightly better, but not by much.&lt;br /&gt;&lt;br /&gt;Here's a diagram that's a bit more relevant to what we're doing.&lt;br /&gt;&lt;img src="http://eschew.org/mirror/acm/projections.png" width="400" height="280" title="linear projections"&gt;&lt;br /&gt;Suppose we have the line segment (vector!) AB, and the point P. We wish to find the coordinates of the point Q on AB that is closest to P. Sound familiar? Luckily for us, the wonderfulness of linear algebra makes this easy. So we just take the direction vector AP -- that's (P - A) -- and project it onto the direction vector AB. That gives us a direction vector AQ, which we add to point A to yield... the point Q! Magical stuff, math is. All of that, with two lines of code.&lt;br /&gt;&lt;tt&gt;P       proj(P v, P u) { return u * P(dot(u,v)/dot(u,u)); }&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Going back to the picture with the blue lines, we now have a concrete method for finding those &lt;tt&gt;q&lt;/tt&gt; values. There's just one problem -- we're actually doing projections onto the LINE AB, not just the line segment. So, when we're doing it, we might get points that aren't actually on our road. Not good, but the fix is simple: if the point is off the line segment, instead use whichever endpoint of the segment is closest to the point. Okay, so how do we figure out when a point is on (or off) a given line segment?&lt;br /&gt;&lt;br /&gt;There are two approaches we can take here. The first is to solve the more general problem of "where is a given point in relation to a given vector?" Called the ccw function, short for counter-clockwise, it takes three points a, b, and c, and determines whether going from a to b to c requires a clockwise, counterclockwise, or no turn at all. We can use the &lt;a href="http://en.wikipedia.org/wiki/Cross_product#Example_2"&gt;cross product&lt;/a&gt; to get a signed area for the parallelogram defined by the vectors ab and ac (labeled &lt;b&gt;&lt;font color="#ff00ff"&gt;a&lt;/font&gt;&lt;/b&gt; and &lt;b&gt;&lt;font color="#008000"&gt;b&lt;/font&gt;&lt;/b&gt; on the wikipedia page). If the area is zero, the points a, b, and c all fall on the same line; otherwise, a turn is required, and the whole function is perhaps half a dozen lines.&lt;br /&gt;&lt;tt&gt;double cross(P a, P b) { return -imag(a*conj(b)); }&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;ccw is one of the building blocks used in finding convex hulls and the area of arbitrary convex polygons, two other geometry problems that crop up quite often in ACM contest problem sets. I used it last year on a problem that involved finding the area of the intersection of convex hulls. However, it has a problem. Computers are limited in the precision of the numbers they can manipulate. So sometimes, the area that the cross product will return won't be 0, it'll be a very, very, very small number, like one-quadrillionth (&lt;tt&gt;1e-15&lt;/tt&gt;). That bites (so to speak), and it bit me. So, anyways, we &lt;strong&gt;could&lt;/strong&gt; use ccw to determine whether or not the q-points we've computed fall within the line segment or not. But that would be overkill.&lt;br /&gt;&lt;br /&gt;More specifically, doing so would ignore information we already have about those q-points: namely, they aren't arbitrary points. We know that they fall somewhere along the &lt;em&gt;line&lt;/em&gt; AB, we just don't know if they fall within the line &lt;em&gt;segment&lt;/em&gt; AB. So the problem we're actually faced with is equivalent to a much simpler problem: if we draw a box around AB, does our q point lie inside the box?&lt;br /&gt;&lt;img src="http://eschew.org/mirror/acm/bounds.png" width="400" height="280" title=""&gt;&lt;br /&gt;It looks like we can simplify even further, to merely ask: does our point fall within the bounds of the x-coordinates of the line? After all, if it falls outside the bounds of the x-coordinates, it cannot be on the line segment. However, contrary to &lt;a href="http://gregmankiw.blogspot.com/2008/01/funny-perhaps-but-illogical.html"&gt;Mike Huckabee's misguided beliefs&lt;/a&gt;, (~X -&amp;gt; ~S) -/-&amp;gt; (X -&amp;gt; S). In particular, checking only the X coordinate and not the Y will fail in the case of points on a straight vertical line.&lt;br /&gt;&lt;br /&gt;Now, finally, we have all the pieces we need. Calculate weights, then do find shortest paths with a standard algorithm. The devil, as always, is in the details.&lt;br /&gt;&lt;br /&gt;For those who want it, here's &lt;a href="http://svn.eschew.org/projects/cs/acm/2006WorldProblems/GSM/GSM2.cpp"&gt;the full C   program&lt;/a&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:73177</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/73177.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=73177"/>
    <title>Speech Recognition Poetry</title>
    <published>2008-01-25T19:47:10Z</published>
    <updated>2008-01-25T19:47:10Z</updated>
    <category term="speechrecognition"/>
    <content type="html">One more bit of speech recognition poetry:&lt;br /&gt;&lt;blockquote&gt;At the one who in the heart and make it home&lt;br /&gt;that in his first alerted eight when he didn't have a duty to&lt;br /&gt;pretend that have lent an eight-DOS attack&lt;br /&gt;it has our neighbors down here were using her get her a hug her head to head the hello you don't have clearly were&lt;br /&gt;the error rate has&lt;br /&gt;had his day that the&lt;br /&gt;Iran arms dealer who died in one of the times&lt;br /&gt;the Ingraham her while using her head and all who really girl who lived in her&lt;/blockquote&gt;&lt;br /&gt;That's from Vista trying to transcribe a recording of my roommate's finance class lecture. The more you try to comprehend it, the less sense it will make.&lt;br /&gt;&lt;br /&gt;But I do love that turn of phrase: "an eight-DOS attack." Heh.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:72919</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/72919.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=72919"/>
    <title>cat | say | transcribe</title>
    <published>2008-01-23T19:37:59Z</published>
    <updated>2008-01-23T19:37:59Z</updated>
    <category term="speechrecognition"/>
    <content type="html">So, apparently I was quite remiss  with my last post. I was, apparently, supposed to take my last exploration with speech recognition to its logical conclusion, and see what happens when the computer tries transcribing its own "voice."&lt;br /&gt;&lt;br /&gt;So, we'll take a text file containing a snippet of text, run that through &lt;a href="http://sudo.livejournal.com/72420.html"&gt;Say.exe&lt;/a&gt; to produce a WAV file, run the WAV file through &lt;a href="http://sudo.livejournal.com/72420.html"&gt;Transcribe.exe&lt;/a&gt; to produce a text file, and compare the two text files.&lt;br /&gt;&lt;br /&gt;Here's &lt;a href="http://en.wikisource.org/wiki/Pride_and_Prejudice/Chapter_1"&gt;the introduction to Pride and Prejudice&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.&lt;br /&gt;&lt;br /&gt;However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered the rightful property of some one or other of their daughters.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Here's what the older Windows XP recognition engine produces. As before, the lack of punctuation is expected.&lt;br /&gt;&lt;blockquote&gt;A's the truth universally acknowledged that a single man in possession of the good fortune that the unwanted the wind out average little known the feelings organisms that chain and maybe I've his first entered a bridge read this to the cell wealth extend the minds of the surrounding families that he is considered the rightful property on someone or other of their daughters&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And Vista's newer engine:&lt;br /&gt;&lt;blockquote&gt;He is a truth universally acknowledged that a single man in possession of a good fortune&lt;br /&gt;part B1 of the white pal ever little down the feeling for the use of such a manner beyond year's first entry neighborhood this truth in cell lab fixed in the mind of the surrounding family's that he is considered a rightful property at someone or other of the daughters&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Interestingly, Vista's output isn't significantly better than XP's. Past experience showed that Vista transcribes more accurately given the same input. Thus, we are led to an intriguing hypothesis: in an effort to create a more natural-sounding computer voice for Vista, Microsoft also created a voice that was more difficult to automatically transcribe!&lt;br /&gt;&lt;br /&gt;Another example, this time using Shakespeare's Sonnet 68:&lt;br /&gt;&lt;blockquote&gt;  Thus is his cheek the map of days outworn,&lt;br /&gt;  When beauty lived and died as flowers do now,&lt;br /&gt;  Before these bastard signs of fair were born,&lt;br /&gt;  Or durst inhabit on a living brow:&lt;br /&gt;  Before the golden tresses of the dead,&lt;br /&gt;  The right of sepulchres, were shorn away,&lt;br /&gt;  To live a second life on second head,&lt;br /&gt;  Ere beauty's dead fleece made another gay:  &lt;br /&gt;  In him those holy antique hours are seen,&lt;br /&gt;  Without all ornament, it self and true,&lt;br /&gt;  Making no summer of another's green,&lt;br /&gt;  Robbing no old to dress his beauty new,&lt;br /&gt;    And him as for a map doth Nature store,&lt;br /&gt;    To show false Art what beauty was of yore.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I added linebreaks to Vista's output, to better enable comparisons between the two versions:&lt;br /&gt;&lt;blockquote&gt;Not that his cheek and at a denny's out&lt;br /&gt;120 minutes and I has flowered now&lt;br /&gt;the forties bastard signs of tired were born&lt;br /&gt;all orders to inhabit, leading brown&lt;br /&gt;deflected golden tresses added that&lt;br /&gt;the right of sepulcher sit where slightly delayed&lt;br /&gt;a second light on secondhand&lt;br /&gt;terribly stabbed Fleetwood another game&lt;br /&gt;became those calling NT Cal sky scene&lt;br /&gt;but not all or none at itself a true&lt;br /&gt;B. Demille summer of another screen&lt;br /&gt;prodding know all too dressy is getting you&lt;br /&gt;  at ms foreign at Tiffany to restore&lt;br /&gt;  to show false are like the meet with your&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I didn't bother with XP.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:72420</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/72420.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=72420"/>
    <title>Transcribe-n-Say</title>
    <published>2008-01-18T05:50:34Z</published>
    <updated>2008-01-23T19:39:21Z</updated>
    <category term="speechrecognition"/>
    <content type="html">Doing the &lt;a href="http://sudo.livejournal.com/72085.html"&gt;transcriptions for Glenn Kelman's presentation&lt;/a&gt; earlier this week ended up taking more time than I expected it to. I can type reasonably quickly, 50 words per minute, perhaps 90 if I concentrate hard and stay away from the Backspace key. But a normal rate of speech is about 130 words per minute, so I can only transcribe about a sentence at a time. So the transcription process goes like this: Listen to audio, transcibe a sentence, seek the audio back a few seconds, repeat. Not the most exciting work around.&lt;br /&gt;&lt;br /&gt;So I figured, hey, what about having the computer transcribe stuff for me? Windows XP itself doesn't come with speech recognition built-in, but Microsoft includes a speech recognition engine with Office XP and 2003, and also has one included as part of the free &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5e86ec97-40a7-453f-b0ee-6583171b4530&amp;amp;displaylang=en"&gt;Microsoft Speech API (SAPI 5.1) SDK&lt;/a&gt;. And all five versions of Vista come with an &lt;a href="http://www.extremetech.com/article2/0,1558,2109974,00.asp"&gt;updated, more-accurate engine&lt;/a&gt;. (For those of you keeping score at home, that would be Home Basic, Home Premium, Business, Enterprise, and Ultimate. Phew!)&lt;br /&gt;&lt;br /&gt;Anyways, SAPI itself has a few simple functions that do most of the work for us in doing a transcription. Basically, you take a stream, bind it to a (WAV) file, pass that stream to the speech engine, enable "dicatation mode," and print out what the the engine thinks it hears. File to stream to engine to recognized text.&lt;br /&gt;&lt;br /&gt;That didn't seem too complex, so I set out to write a quick C# command-line app to do that. For the most part, even though it wasn't designed with C# in mind, the COM interop story for SAPI 5.1 is pretty good. Unfortunately, the C#-language binding for the SpStream.BindToFile function is a little iffy. The C++ type signature for the file name is &lt;code&gt;const WCHAR *&lt;/code&gt;. Somehow, that got translated into &lt;code&gt;ref ushort&lt;/code&gt;. Not so good. I found a post from one Microsoft employee, Dave Wood, which acknowledged this &lt;a href="http://www.mcse.ms/showthread.php?t=552878"&gt;problem with SAPI&lt;/a&gt;, and also gave suggested workarounds. However, I figured that, considering how simple the app would be, I might as well just write it in C++.&lt;br /&gt;&lt;br /&gt;Well, I did. The hardest part turned out to be learning about the &lt;a href="http://64.233.169.104/search?q=cache:5_XUnl1lrLwJ:www.hal-pc.org/~abeld/cppsighal/vcppstrings.htm+wchar+ansi&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;cd=1&amp;amp;gl=us"&gt;multitudes of string representations in Win32 COM&lt;/a&gt; programming, and how to translate between them. A little reading of documentation, sample code, and other examples online, and I had something that worked. No error handling logic in place, but it worked.&lt;br /&gt;&lt;br /&gt;For certain values of worked, anyways. By "worked," I mean that it fed the WAV data to the speech recognition engine, and got results back. The usefulness of those results is another issue entirely. &lt;br /&gt;&lt;br /&gt;First, the source of the WAV makes a pretty big difference in recognition accuracy. This makes a bigger difference when using the older version 5.1 recognizer on XP than Vista's newer version 8.0, but it's noticeable on both. A WAV file I created using Audacity and a speech-recognition-tuned microphone yielded decent results on XP and great results on Vista. A snippet of the audio from Kelman's presentation, converted to WAV format, was... spottier. I manually ran Audacity's "Normalize" command to make the waveform graph more similar to the mic's recording, and that improved recognition accuracy somewhat. Unfortunately, the results on XP are comical and, at times, almost poetic.&lt;br /&gt;&lt;br /&gt;I recorded &lt;a href="http://eschew.org/media/audio/tenyears.wav"&gt;this sample WAV file&lt;/a&gt;, which is just me saying "Computing research has made remarkable advances, but there's much more to be accomplished. The next ten years of advances should be even more significant, and even more interesting, than the past ten," which is simply the first two sentences from &lt;a href="http://norfolk.cs.washington.edu/htbin-post/unrestricted/colloq/details.cgi?id=648"&gt;the abstract of Ed Lazowska's UWash talk&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's what the version 5.1 recognizer thought it heard: "Computing research has made remarkable advances but there's much more of a published the next ten years of events this should be even more significant and even more interesting from the past ten." Close, but not quite. The lack of periods and puctuation is expected, but turning "to be accomplished" into "of a published," well, not so much.&lt;br /&gt;&lt;br /&gt;Vista's version 8.0 recognizer does much better: "Computing research has made remarkable advances but there's much more to be accomplished the next 10 years of advances should be even more significant and even more interesting than the past 10." Flawless! Note that Vista is smart enough to turn "ten" into "10." Not such a big deal here, but it's much nicer to read "5,313,852" than "five million three hundred thirteen thousand eight hundred two." Anyways, I think that's pretty darn impressive for a completely untrained speech-recognition system.&lt;br /&gt;&lt;br /&gt;Unfortunately, the results on Kelman's presentation weren't nearly as good. I took a short clip of his presentation, which I transcribe as "... man. I learned how to do everything. And, uh, a couple of years later I started Plumtree Software with a few of my friends. And if you can start a company, um, everyone will tell you it's too soon, um. And I'm sure they'll be right, there were so many things that I didn't know, ah, when I started Plumtree, and I erred egregiously, uh, and really suffered for it. But, ah, you'll never know everything..."&lt;br /&gt;&lt;br /&gt;First, Vista's valiant attempt. It gets points, I suppose, for including recognizable phrases from the original audio. Knowing what the real transcription is, we can see a mutilated version of it here, and I think you can get a general sense of what the original audio was saying. Not all the fine points, but the general sense, sure.&lt;br /&gt;&lt;blockquote&gt;A man I learned how to do everything&lt;br /&gt;and got a couple years later I started onto software will hit my friends&lt;br /&gt;and if you can set a company of everyone will tell you that it's too soon&lt;br /&gt;hung at sure it'll be right there are some things that I didn't know how I started entree am a grievously on&lt;br /&gt;and really suffered for it but the deal ever now everything&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Meanwhile, here are a few of XP's attempts. These are all with the exact same input file, mind you. Same input, very different outputs.&lt;br /&gt;&lt;blockquote&gt;Air guard had every hour at our doorstep start of his software NFS at its start out&lt;br /&gt;that are out how data it's too soon&lt;br /&gt;that ensured underwriter scientists I didn't know that I saw it and trade vendor who displayed (suffered a heart&lt;br /&gt;out ever known everything&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Event that my head.)&lt;br /&gt;and not to use their instead of his software Jennifer and 75¢ of the&lt;br /&gt;outdoor elements out in a season&lt;br /&gt;that ensure the main) so it's I didn't know that aside and trade at graciously I suffered during&lt;br /&gt;the demo never know everything&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;That men have everything at Gottschalks understand outside of his software to the outset if you can start company&lt;br /&gt;founder of how the united states suing&lt;br /&gt;that ensure the main) scientist I didn't know&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;It's really sort of poetic, in its own twisted way.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;So, anyways, if you have XP or Vista, and don't mind tinkering with basically-untested software, you can &lt;a href="http://eschew.org/projects/speech/transcribe.exe"&gt;download Transcribe.exe&lt;/a&gt; and test it yourself. XP users will probably need to download and install the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5e86ec97-40a7-453f-b0ee-6583171b4530&amp;amp;displaylang=en"&gt;SAPI SDK 5.1&lt;/a&gt; in order to get a speech recognition engine installed. Users of both XP and Vista may (or may not) need to install the &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=200B2FD9-AE1A-4A14-984D-389C36F85647&amp;amp;displaylang=en"&gt;Visual Studio 2005 C Runtime components&lt;/a&gt;, depending on what other software you've already got installed.&lt;br /&gt;&lt;br /&gt;Usage is simple: pass in the name of a WAV file to read from, and the name of a file (probably .txt) to output the results to. On my computer, a 2.0 GHz Core 2 Duo, it transcribes at roughly 3x realtime.&lt;br /&gt;&lt;br /&gt;Having the ability to transcribe without easy speech synthesis felt like having yin without yang. So, enter &lt;a href="http://eschew.org/projects/speech/say.exe"&gt;Say.exe&lt;/a&gt;. It's even simpler than Transcribe. It, too, is a command-line application. &lt;br /&gt;&lt;a href="http://www.flickr.com/photos/brk/2201348682/" title="say.exe usage by Ben Karel, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2118/2201348682_70a623f1a1_o.png" width="669" height="169" alt="say.exe usage" /&gt;&lt;/a&gt;&lt;br /&gt;If the first argument is a file, the other arguments are ignored and whatever the file contains is passed to the default TTS voice to speak. If the first argument is not a file, whatever arguments are provided are passed to the default TTS voice to speak.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://eschew.org/projects/speech/say.exe"&gt;Say.exe&lt;/a&gt; is written in C#, and targets the .NET Framework version 3. It should run on Vista without any other downloads required, but XP computers that don't have it yet will need to &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=10CC340B-F857-4A14-83F5-25634C3BF043&amp;amp;displaylang=en"&gt;download .NET Framework 3.0&lt;/a&gt; first. &lt;br /&gt;&lt;br /&gt;Please note that both of these apps were written with no real error handling to speak of. I don't think anything disastrous should go wrong with them, but for all I know they could turn mutant and eat your files, your leftovers, and your houseplants. Then again, I doubt it.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:72085</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/72085.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=72085"/>
    <title>Glenn Kelman: How to Get the Most Out of a Startup</title>
    <published>2008-01-13T06:17:24Z</published>
    <updated>2008-02-06T03:21:39Z</updated>
    <category term="programming video"/>
    <content type="html">I've been reading more about two things lately: startups and investing. Well, that's not entirely accurate. I've been coming to the slow realization that programming, while fun, makes up less than half of what it takes to be a successful software engineer. The thing is that professional "programmers," from what I've read, end up spending less than half their time programming. The rest of it is spent with wetware ops, interacting with (gasp) actual people, directly or indirectly. So writing, interpersonal skills, luck, and business acumen each contribute at least as much as raw programming skills do in the creation of a "good" coder.  Well, I can't do much about luck, and between business and human relations, I find the business side of things more palatable, so I've been looking at how things work from a business perspective.&lt;br /&gt;&lt;br /&gt;I've also realized that I don't particularly want to work for a super-large company, nor am I interested (at the moment) in doing fundamental research or teaching. That leaves startups, small businesses, and contracting work as the most-plausible means of gainful employment. And all three of those paths benefit greatly from knowing a bit about the business side of things. So, I've been independently investigating the subset of the business world that seems most directly applicable to my immediate future. That means reading about finance, investing, MBAs, and tech startups, as well as taking Macroeconomics over the winter session. In the last week, I've come across quite a few bits about startups, both purposefully and incidentally. Here's one of the incidental ones: &lt;a href="http://norfolk.cs.washington.edu/htbin-post/unrestricted/colloq/details.cgi?id=654"&gt;a talk given at the University of Washington by Glenn Kelman&lt;/a&gt;. I stumbled across it because UWash's RSS feed got horked and displayed 87 older talks; Glenn's was one of the ones in the list that caught my eye.&lt;br /&gt;&lt;br /&gt;As a CS student, the whole general dichotomy of "stable, big, boring" established companies versus "small, dynamic, risky, exciting" startups is ever present. But there's a difference between knowing that something is different, and knowing how to take advantage of that difference. Luckily, Glenn Kelman, the guy who &lt;s&gt;started&lt;/s&gt; &lt;em&gt;is now CEO of&lt;/em&gt; &lt;a href="http://redfin.com/stingray/do/start"&gt;Redfin&lt;/a&gt;, &lt;em&gt;and co-founded Plumtree Software,&lt;/em&gt; knows a thing or two about startups. Glenn is a relaxed and funny presenter, a pleasure to listen to and learn from.&lt;br /&gt;&lt;br /&gt;I highly recommend checking out &lt;a href="http://norfolk.cs.washington.edu/htbin-post/unrestricted/colloq/details.cgi?id=654"&gt;UWashington's archive of Glenn's talk&lt;/a&gt;. Here's a selection of quotes from Kelman that I found interesting:&lt;br /&gt;&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;"Stanford has this very entrepreneurial environment, they're in Palo Alto, very close to Google and Facebook, they're insufferably bright and very arrogant, and they know all about the world of venture capital and startups. And when you try to hire a Stanford student, you'll give them the offer, of course it will be this ridiculous offer, you'll expect them to be overcome with emotion and instead he'll say "Well, I'm going to talk to my parents, I'll talk to my family attorney, I'll come back to you tomorrow with a counteroffer," and you spend about a week negotiating terms, mostly around the equity..."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"If you can start a company, everyone will tell you that it's too soon. And I'm sure they'll be right. There are so many different things that I didn't know when I started Plumtree, and I erred egregiously, and really suffered for it. But you'll never know everything you'll need to know, and if you have a great idea you should start a company."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"And if you go to Stanford, you tend to have a sense of entitlement that's fairly elaborate..."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"What you get at a large company is exposure to different types of career tracks... And of course the job security is fantastic. And if you work at IBM, you work at Microsoft, you work at Amazon, it's hard to imagine that you'll either get laid off or even fired. I think it's very difficult at a large company to screw up so bad that you'll get fired. Whereas at a small company like Redfin, we fire people all the time, we really do."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"I think there's really a challenge to fill the emotional void that college leaves in you. You know, there's these dorms where you stay up all night arguing about stuff, and playing video games, or doing whatever you do. And when you get out of school, there's nothing quite like that. The closest thing I've ever seen is a startup."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"The thing you've got to remember is that about 80% of startups fail. That's an actual statistic, it's 82% fail. So odds are your startup will fail. [...] Nobody's that good at picking which seed will grow and which won't."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Focus on one thing when you're interviewing, which is getting an offer. Then they've given all the control to you."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Most importantly, you have to hate their competition. If you're going to interview at Microsoft, you want to tell Microsoft how you want to destroy Linux. [...] You want to tell them you want to destroy Linux, and that's what gets you out of bed in the morning. Because for whatever reason, they've got this weird emotional allegiance to some competitor you've never heard of, and that competitor's destruction. So you need to make sure you're in line with destroying them."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"You need to understand what you care about, and then show the passion. So many people put the suit on, and try to be all square, and professional, and grownup. But really you'll be better of if you let the beast out, and show how enthusiastic you are. I was just interviewing a bunch of people yesterday in Berkeley, and it was the ones who were really trying to seem adult that did the worst, and it's the ones who were almost childishly enthusiastic about some CS project that they worked on, or a robot that one guy built, that really totally won me over. And I think that all human beings are the same way in that respect. If you screw up, and you will, just say you screwed up! So many times in an interview, I've said something that wasn't quite right, and they've moved on, but I'm still thinking about it for twenty minutes, I'm sitting there thinking about the one question I screwed up at the beginning. And it's totally cool to just say "Hey, before I go, there's just one thing that I screwed up and I wished I'd done it right" [...] Go back and fix it, you'll feel better about yourself and then you can move on. Oh yeah, and don't ramble. When they ask a question, if you don't understand the question, you need to stop and make sure you understand it, then answer it directly. The best answers are "Yes", "No", or a number. Just think about that."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"An offer is never revoked. [...] Once it's on the table, [...] you can ask for crazy things and see what happens."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"You need to understand every single thing in that offer before you begin negotiating. So just ask as many questions as you can, and then instead of trying to respond on the spot -- there's a tremendous impulse to do that, people are going to say "Well what do you think, does it look good?" -- you can just say "Hey, you know, this is my first time through,  I don't know if it looks good or not, lemme just think about it and I'll give you an answer tomorrow.""&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"At some level, if you can say, "I wanna work here, but this is want I need to make. If you offer me this, it closes the deal." --  best negotiating tactic ever."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Some people do this acceleration deal [...] where as soon as there's an acquisition, everything they owe you they give you all at once, and you can wash your hands of that place, and you're done. And that's what all the big shots try to get when they negotiate a deal, it's hard to get if you're a little shot."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Generally, the reason you should work at a startup isn't so you can [cash out], it's so you can get a ton of responsibility and you can have the emotional rewards of working on a small team to build something really great."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Oh, the sweet thing about stock, by the way, not that you care at this point in your career, is that the regressive American tax code doesn't really tax you on it the way that it should. One reason to vote Republican, I guess."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Oh, one other little trick, by the way, that I think is really useful. If you can't figure out what the options are worth, just make them do it. Say "If I were willing to take a $5000 pay cut, how many more options would you give me?" And if they cut the pay by $5k and give you 1 million more options, they must not think those options are worth much."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"I'd take a crappy job at a good startup over a good job at a bad startup. Because basically you're trapped on a spaceship, you're in this little enclosed world. If that spaceship is headed towards the sun, and going to incinerate you, it doesn't matter if you're the grand king of that spaceship or you're the guy cleaning the toilets: you're gonna fry."&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;There are oodles more quotes in the video. Watch &amp; enjoy!&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;Edit 1: Corrected factual error re: Glenn's role at Redfin, plus assorted typos.&lt;/small&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:22683</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/22683.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=22683"/>
    <title>Vista</title>
    <published>2007-12-23T23:36:54Z</published>
    <updated>2007-12-23T23:36:54Z</updated>
    <content type="html">So, I've had Vista (64 bit) installed for about a week now. I actually like it, from a user interface perspective, more than XP. It has a lot of nice touches:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;When you go to restart your computer, and there are programs still running, it gives you &lt;a href="http://en.wikipedia.org/wiki/Image:Vista_Shutdown.gif"&gt;a nice list of the programs preventing a restart&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Searchable start menu&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Windows Explorer Breadcrumb Bar&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Image:Windows_Vista_Explorer.png"&gt;Explorer at-a-glance drive usage bars&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;More attractive icons&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Revamped, easier-to-use sound control panel&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Much saner (fewer spaces!) filesystem layout for user home folders.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Related: no more "My" prefix!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Related: Separate Desktop and Downloads folders.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Task Manager -&amp;gt; Resource Monitor is nice&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Explorer's taskbar: Organize -&amp;gt; New Folder&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Features I was looking forward to using, but didn't get a chance to play with:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Speech recognition&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Per-app sound controls&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ink&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Not-so-great things:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;When bringing up a context menu, you have to click the actual name of a file in Details view, otherwise you get the parent folder. This bit me again and again.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Useless additions: Sidebar, rearranged control panels, &lt;/li&gt;&lt;br /&gt;&lt;li&gt;User Account Controls&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Un-tweakable Explorer taskbar buttons, especially Burn&lt;/li&gt;&lt;br /&gt;&lt;li&gt;App compatibility: iTunes doesn't burn CDs out of the box, and bootable-USB-flash-drive utilities (based on old 16-bit code) don't work period.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Explorer.exe stability issues. In one week, it unexpectedly quit five times.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Overall, I was happy with Vista for the price I paid (that is, nothing, thanks to MSDNAA). I didn't find Vista sluggish, thanks to four gigs of RAM. When I had only 1 GB installed, it was much more painful. I wouldn't recommend using it with anything less than two GB.&lt;br /&gt;&lt;br /&gt;The not-so-great things about it were mostly ignorable or disable-able, so I would have stuck with it. Unfortunately, the other thing that went wrong was that I'd get complete system freezes, usually after a toaster box popped up saying "The graphics driver stopped responding and recovered successfully." This would happen every two or three days. Not often enough to debug, but regularly enough that, after the third time, I could see it wasn't going to stop. It happens at stock speed, and even more frequently when overclocked. Other than that, the system is orthos stable and memtest clean.&lt;br /&gt;&lt;br /&gt;I suspect the culprit here is Vista's new WDDM driver model. The new driver model may lead to fewer stability issues in the future, it's possible. Unfortunately, at the moment, the graphics car makers have dozens of years of experience writing drivers under the old model, and roughly one year of experience of having actual people run their Vista drivers.&lt;br /&gt;&lt;br /&gt;So, it's back to 32-bit Windows XP for me. It was a fun experiment while it lasted, and I think it's good to form one's own opinions. Maybe in another year or three, whenever I next upgrade my processor, I'll re-evaluate Vista. More likely, though, I'll move to Ubuntu by that time. Oh well.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:22415</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/22415.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=22415"/>
    <title>New Computer!</title>
    <published>2007-12-19T10:08:26Z</published>
    <updated>2007-12-19T10:08:26Z</updated>
    <content type="html">&lt;a name="cutid1"&gt;&lt;/a&gt;&lt;br /&gt;Old and busted:&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/brk/2121716357/" title="IMG_0009 by Ben Karel, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2333/2121716357_ef56e06838.jpg" width="375" height="500" alt="IMG_0009" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note dust, multiple hard drives + 80mm fans (loudness), tangle of wires.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;New Hotness:&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/brk/2121718241/" title="Internal Case Layout 1 by Ben Karel, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2027/2121718241_8c68e1c72b.jpg" width="375" height="500" alt="Internal Case Layout 1" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Virtually silent. May upgrade processor and heatsink in a year or two and get that much closer to actually silent. Unfortunately I had to cut off the top of the northbridge heatsink to get the Freezer 7 Pro to fit. Not a huge deal, it was really only there for cosmetic reasons anyways. Also, there are actually more wires in the picture than there are in the computer now. In particular, the little fan controller for the Rosewill 120mm fan (not pictured) didn't keep the fan quiet enough for me, even at the lowest setting, so it's out.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Still working on getting my software environment back up to speed. Installed Vista Business x64 (thanks, MSDNAA!), and it worked fine for a day or two until it got into a mysterious infinite-reboot loop on bootup. Then Ubuntu x64 install froze, as did XP x64 AND both 32- and 64-bit editions of Vista. After two further days of banging my head against the wall, Vista's install disc magically started working again, and a quick System Restore put things back in good working order. I'm still not sure what caused the CD issues in the first place. I suspect the install got corrupted from either Daemon Tools or, most likely, AnyDVD. Will very very cautiously approach those apps in the future.&lt;br /&gt;&lt;br /&gt;&lt;s&gt;Sadly, iTunes (specifically, CD writing) doesn't work in 64-bit Windows yet. iTunes will run in a virtual machine, but sound is staticky. Better than it was on the old machine, but still not good enough. That means my options are, at the moment, 32-bit XP or Vista, or Ubuntu with Amarok or Banshee.&lt;/s&gt; OK, it looks like manually installing a 64-bit CD driver for iTunes makes everything except iPhone syncing work. Good enough for me, I neither have nor want an iPhone.&lt;br /&gt;&lt;br /&gt;Anyways, Ubuntu is a possibility, but I don't (yet?) have a strong ideological preference for it, and it has a number of things going against it:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Migrating a 65 GB iTunes library would be a pain&lt;/li&gt;&lt;br /&gt;&lt;li&gt;From what I've seen, Linux doesn't have much going on in speech recognition yet. Maybe in 5 or 10 years, Google will share the 411 love...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In a related note, hardware support isn't quite up to par for things like the MX Revolution mouse. There are hacks that will let you change the mouse wheel mode from the CLI, but nothing like SetPoint's context-sensitive behavior switching.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I do like playing the occasional game, which was after all the entire point of getting a nice graphics card in the first place. Thus, I could either run Linux and dual-boot, or just run Windows.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;In the future, when I have more money and less time, the solution to all of these problems will probably be to buy a Mac. For now: I actually like Vista so far. The plan is to craigslist 2 of the 6 GB RAM in the pic now, before memory prices drop even further, and make do with ~3.5 GB of RAM for the next few years.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:21475</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/21475.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=21475"/>
    <title>Chess Club memories</title>
    <published>2007-03-07T16:34:52Z</published>
    <updated>2007-03-07T16:34:52Z</updated>
    <content type="html">&lt;a href="http://xkcd.com/c232.html"&gt;&lt;img src="http://imgs.xkcd.com/comics/chess_enlightenment.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;:-)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:21002</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/21002.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=21002"/>
    <title>acceptance and hypocrisy</title>
    <published>2007-02-27T05:52:28Z</published>
    <updated>2007-02-27T05:52:28Z</updated>
    <content type="html">So Lauren, Jess and I went to a "program" being held by a senior fellow tonight. It basically involved us sitting around and talking while consuming organic food. Wild Oats sparkling fruit drinks, Newmans-Os oreo knockoffs, that sort of thing. &lt;br /&gt;&lt;br /&gt;The Girl who put it on... I don't know her name. She said she was from New York. She had nice hair and an upturned nose. And the things she said... mmm.&lt;br /&gt;&lt;br /&gt;Start by saying how she's in Ray Street -- the dorm I lived in last year -- and how she was surprised that they were placed in a special-interest community (in her case, Environmental Conservation or some such innocuous circlejerk). "A special community? I mean, what, do they think I'm stupid?" &lt;br /&gt;&lt;br /&gt;Pick up the conversation a few minutes later, and she's commenced to ranting in even tones about how "unaccepting" the UD community is. We form cliques, we're unaccepting, we're not friendly.&lt;br /&gt;&lt;br /&gt;"Isn't that just human nature, though? I mean, you said you were a polisci major. Doesn't history show us that people tend to clump together into groups and distinguish 'us' from 'not us' based on shared properties and interests?"&lt;br /&gt;&lt;br /&gt;"It's worse here than other places," she says. "What other places?" I inquire? After some avoiding the question and repeating her unsupported assertions, she relents: "Brown. Brown isn't like this." "And what's the tuition at Brown now? Thirty five thousand a year?" I ask. "Oh, no, at least 43!" she exclaims. "You don't think maybe that people who are smart and/or rich enough to go to Brown form something of a self-selecting group? That Brown is, compared to UD, just a single large clique?" No, that doesn't seem to hit the spot.&lt;br /&gt;&lt;br /&gt;"College students are supposed to be, you know, big liberals, but people here aren't like that."&lt;br /&gt;&lt;br /&gt;A mutual friend of ours, accompanied by an unknown young man, pokes her head in and smiles. "Hey guys!" she says. "Hey, we're talking about energy conservation! Do you want to come in?" The Girl says. "No, sorry," says Mutual Friend, smiling sweetly. "I have a lot of homework to do tonight. Have fun though!" The Girl waves and mutters under her breath "Guess boys are more fun than us."&lt;br /&gt;&lt;br /&gt;"She said something about being accepting?" I whisper into Lauren's ear. We both crack up laughing. &lt;br /&gt;&lt;br /&gt;We left soon after that, growing ever more eager to escape this polished cheese grater.&lt;br /&gt;&lt;br /&gt;Jess, it turned out, was thinking the same thing. And when Lauren Isaacs curses your name, you know you've done something wrong.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:20581</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/20581.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=20581"/>
    <title>For Lauren, of course</title>
    <published>2006-12-13T06:34:03Z</published>
    <updated>2006-12-13T06:34:03Z</updated>
    <content type="html">&lt;blockquote&gt;Lauren: "Hey Ben, Jess and I are going to Harry Mart, do you want to come?"&lt;br /&gt;[Ben pauses and considers]&lt;br /&gt;[Lauren smiles impishly]&lt;br /&gt;Lauren: "You could go back to your dorm, you know... and &lt;em&gt;program!&lt;/em&gt; Oooh, programming!"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://xkcd.com/c196.html"&gt;&lt;img src="http://eschew.org/images/mirror/command_line_fu.png"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Artist's comment:&lt;br /&gt;&lt;blockquote style="font-size:75%;"&gt;When designing an interface, imagine that your software is all that stands between the user and hot, sweaty, tangled-bedsheets-fingertips-digging-into-the-back sex.&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:19740</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/19740.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=19740"/>
    <title>Unix `sudo`, a layman's explanation</title>
    <published>2006-08-30T14:29:58Z</published>
    <updated>2007-12-15T19:34:01Z</updated>
    <content type="html">&lt;img alt="" xwaish="1" src="http://imgs.xkcd.com/comics/sandwich.png" /&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:19485</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/19485.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=19485"/>
    <title>On lessons, learnt the hard way</title>
    <published>2006-08-04T05:36:11Z</published>
    <updated>2006-08-04T05:36:11Z</updated>
    <content type="html">Note to self: Stick shifts are to be parked in first or reverse, not neutral. Also, just because the parking brake lever isn't horizontal does not mean it's engaged.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:19172</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/19172.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=19172"/>
    <title>Je ne parlerai pas; je ne penserai rien</title>
    <published>2006-07-25T20:17:30Z</published>
    <updated>2006-11-28T04:30:27Z</updated>
    <content type="html">&lt;blockquote&gt;I shall not speak, nor think, but, walking slow&lt;br /&gt;Through nature, I shall rove with Love my guide,&lt;br /&gt;As gypsies wander, where, they do not know,&lt;br /&gt;Happy as one walks by a woman's side.&lt;/blockquote&gt;&lt;br /&gt;-Arthur Rimbaud, March 1870, trans. Jethro Bithell</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:sudo:18755</id>
    <link rel="alternate" type="text/html" href="http://sudo.livejournal.com/18755.html"/>
    <link rel="self" type="text/xml" href="http://sudo.livejournal.com/data/atom/?itemid=18755"/>
    <title>sudo @ 2006-07-09T22:22:00</title>
    <published>2006-07-10T02:26:17Z</published>
    <updated>2006-07-10T02:26:17Z</updated>
    <content type="html">&lt;blockquote&gt;You are not nameless to me. Do not remain nameless to yourself -- it is too sad a way to be.  Know your place in the world and evaluate yourself fairly, not in terms of the naive ideals of your own youth, nor in terms of what you erroneously imagine your teacher's ideals are.&lt;br /&gt;&lt;br /&gt;Best of luck and happiness,&lt;br /&gt;Sincerely,&lt;br /&gt;Richard P. Feynman&lt;/blockquote&gt;</content>
  </entry>
</feed>
