<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6809957905702392707</id><updated>2011-10-11T16:00:54.308+13:00</updated><category term='facebook'/><category term='guitar hero'/><category term='es4'/><category term='math'/><category term='colour'/><category term='election'/><category term='java'/><category term='usb'/><category term='encoding'/><category term='web'/><category term='books'/><category term='dynamic'/><category term='static'/><category term='politics'/><category term='poker'/><category term='comic'/><category term='government'/><category term='games'/><category term='music'/><category term='advertising'/><category term='puzzle'/><category term='game theory'/><category term='http'/><category term='blog'/><category term='computers'/><category term='mmp'/><category term='discursive'/><category term='cs'/><category term='life'/><category term='c#'/><category term='bytecode'/><category term='iphone'/><category term='android'/><category term='charity'/><category term='groan'/><category term='apple oops'/><category term='poetry'/><category term='video'/><category term='microsoft'/><category term='unicode'/><category term='tv'/><category term='code'/><category term='statistics'/><category term='money'/><category term='humor'/><category term='broken'/><title type='text'>non-authoritative information</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.abstractable.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-7955488537235311700</id><published>2011-01-18T02:40:00.005+13:00</published><updated>2011-01-18T04:03:58.748+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='cs'/><title type='text'>desktop data structures</title><content type='html'>&lt;blockquote&gt;Most humans when sorting—ordering a deck of cards, for example—use a method that is similar to insertion sort.
 —&lt;a href="http://en.wikipedia.org/wiki/Insertion_sort"&gt;Wikipedia - Insertion Sort&lt;/a&gt;&lt;/blockquote&gt;
The obvious lessons:&lt;ul&gt;
&lt;li&gt;Insertion sort is a simple and intuitive algorithm&lt;/li&gt;
&lt;li&gt;The obvious algorithm is sometimes slow&lt;/li&gt;
&lt;li&gt;Humans optimise for human-sized problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hang on though, when I sort a deck of cards, I do this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sort 5 cards through some intuitive process.&lt;/li&gt;
&lt;li&gt;Grab another card (if there is one)&lt;/li&gt;
&lt;li&gt;Find where it goes&lt;/li&gt;
&lt;li&gt;Insert it&lt;/li&gt;
&lt;li&gt;Go to step 2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But I certainly don't lay all the sorted cards out in a line, and move them all across by one when I insert one into the list. I just make a gap and stick the card in. This doesn't take longer if i have more cards!&lt;/p&gt;
&lt;p&gt;What does take longer is finding the right place to insert a card, but when this gets hard I end up using a modified binary search. (Modified because I know something about the distribution of cards, and because it's easy to look at (and cache) a few consecutive cards). So this is log(n), and the overall algorithm is O(n log n), or as we say in Germany, 'fast'&lt;a href="#dsnote1" name="dscite1"&gt;&lt;sup&gt;[1]&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;The ringbinder&lt;/h2&gt;
&lt;p&gt;We get away from it because real life has a 'data structure' that's half array, half linked list: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;'Get the nth item' is constant time (ish. You get pretty good at estimating how thick 10 cards are)&lt;/li&gt;
&lt;li&gt;Insert an item is constant time.&lt;/li&gt;
&lt;li&gt;Remove an item is constant time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm going to call this structure the 'Ringbinder' because 'Stack' is already taken by something that behaves nothing like any real-life stack I've ever seen. For sufficiently large values of N, your program will run faster using a USB robotic ring-binder operator rather than an ArrayList. You heard it here first.&lt;/p&gt;

&lt;h2&gt;Divserion: quantum bogosort&lt;/h2&gt;
&lt;p&gt;Cheating at algorithms using real-life's weirdnesses isn't new. qfork() is a version of fork() that returns a different value in each &lt;a href="http://en.wikipedia.org/wiki/Many-worlds_interpretation"&gt;quantum universe&lt;/a&gt;. So we sort in O(n) like so:
&lt;pre class="code"&gt;srand(qfork());
shuffle(data);
if(!sorted(data))
   exit(1); // todo cleanup world&lt;/pre&gt;
&lt;p&gt;I mention this only because it amuses me.&lt;/p&gt;

&lt;h2&gt;So, seriously?&lt;/h2&gt;
&lt;p&gt;I guess at some point physically moving the cards to make a gap doesn't actually take constant time. If our robot can exert some fixed force and has to move n items just enough to make room for one more, then this takes O(√n) time&lt;a href="#dsnote2" name="dscite2"&gt;&lt;sup&gt;[2]&lt;/sup&gt;&lt;/a&gt;. Revised performance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to index: O(√n)&lt;/li&gt;
&lt;li&gt;Get next/prev: O(1)&lt;/li&gt;
&lt;li&gt;Insert/delete: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This makes our insertion sort O(n^1.5 log n) which is no longer state of the art. But surely there are currently-optimal algorithms where using this data structure would give better asymptotic performance than we get on our fancy-pants von Neumann machines&lt;a href="#dsnote3" name="dscite3"&gt;&lt;sup&gt;[3]&lt;/sup&gt;&lt;/a&gt;. Or maybe I'm missing something. I'm probably missing something.&lt;/p&gt;

&lt;h2&gt;Any others?&lt;/h2&gt;
&lt;p&gt;What other data structures can you build from common household items that put our silicon masters to shame when it comes to data processing?&lt;/p&gt;
&lt;p&gt;(Using people to demonstrate the power of parallelism doesn't count, &lt;a href="http://youtube.com/"&gt;It's&lt;/a&gt; &lt;a href="http://wikipedia.org/"&gt;been&lt;/a&gt; &lt;a href="http://www.facebook.com/pages/If-we-get-1000000-members-I-will-personaly-kick-justin-beiber-in-the-nuts/312816916320" title="sigh"&gt;done&lt;/a&gt;).

&lt;p&gt;&lt;a name="dsnote1" href="#dscite1"&gt;[1]&lt;/a&gt; working for American software companies is a lousy way to learn German.&lt;/p&gt;
&lt;p&gt;&lt;a name="dsnote2" href="#dscite2"&gt;[2]&lt;/a&gt; F=ma, s = at^2, etc.&lt;/p&gt;
&lt;p&gt;&lt;a name="dsnote3" href="#dscite3"&gt;[3]&lt;/a&gt; and way worse real-world performance, as we're shoveling around &lt;a href="http://en.wikipedia.org/wiki/Avogadro_constant"&gt;avocado-sized&lt;/a&gt; chunks of matter instead of deftly handling &lt;a href="http://www-03.ibm.com/ibm/history/exhibits/vintage/vintage_4506VV1003.html"&gt;individual atoms&lt;/a&gt;. Still.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-7955488537235311700?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/7955488537235311700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=7955488537235311700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7955488537235311700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7955488537235311700'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2011/01/desktop-data-structures.html' title='desktop data structures'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-4969117541894567273</id><published>2010-03-25T22:56:00.003+13:00</published><updated>2010-03-26T00:20:18.103+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='game theory'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>the old man and the cspan</title><content type='html'>&lt;p&gt;I've been watching the USA healthcare fiasco (&lt;a href="http://www.politico.com/news/stories/0310/34982.html"&gt;surely&lt;/a&gt;, the &lt;a href="http://www.huffingtonpost.com/2010/03/24/tom-perriello-tea-party_n_511874.html"&gt;appropriate word&lt;/a&gt;) with a sort of morbid curiosity.&lt;/p&gt;

&lt;p&gt;Although comparisons to the American Civil Rights movement seem a little strained, there is one element that draws the two together in my mind. It's hard to understand, looking back, how reasonable people could have found segregation to be just; similarly I can't find the right cultural lens to see a medical safety net to be unneccessary or even immoral, in a country that &lt;a href="http://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita"&gt;can manifestly afford it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course the difference is that this America is here now, with few cultural barriers from where I sit, and so you can watch it tick in real-time and even converse with it. And sometimes marvel at the schizophrenic behaviour that loves teams but hates collectivism, and values the Constitutional means over the moral ends.&lt;/p&gt;

&lt;p&gt;The high-stakes game theory involved in passing controversial legislation has been fascinating recently. There is a disconnect between the centrist reality&lt;sup&gt;&lt;a href="#healthcare_1"&gt;[1]&lt;/a&gt;&lt;/sup&gt; and the "left-wing" label that the bill is receiving from left and right alike. &lt;a href="http://enthusiasm.cozy.org/archives/2010/03/thoughts-on-health-reform"&gt;Ben Hyde writes:&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;If you map out the left-right spectrum of the nation and the legislatures the reform we got falls at the center.   That was exactly what Obama signaled he would aspire to deliver; going all the way back to the earliest days of his campaign.   As a practical matter this bill is about exactly as far to the left as anybody should have hoped for.  The party on the left doesn’t get to pass a bill that is at the center of it’s party member’s opinions.   You only get to pass a bill that gets you the vote of that last necessary right most legislator.&lt;/blockquote&gt;

&lt;p&gt;That's only the case if those on the right are willing to go without reform. The Republicans clearly are (for this electoral cycle), having made the calculation that an ineffectual government with a Democratic majority will give them a win at the next election. However, the right flank of the Democrats don't have this strategy available to them. If they truly wanted healthcare reform, Ben's logic would equally well suggest that a bill would have to cater to the left of the party. Simple symmetry says that with Republicans out of the picture as potential votes, the bill should indeed be written by the median Democrat if as Ben says:&lt;/p&gt;

&lt;blockquote&gt;But yet [the] old system was on the fast track to making American industry entirely unable to compete.  And hence even those who think that Government’s only function is to help large economic actors were largely in support of reform.&lt;/blockquote&gt;

&lt;p&gt;One would hope so, and the refrain from the holdouts has been "Everyone agrees we need reform, but". The evidence is thin on the ground.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;a name="healthcare_1"&gt;[1]&lt;/a&gt; By US standards. From my perspective, comprehensive government-run healthcare like in NZ or the UK would be favoured by the left, private healthcare funded by taxes (e.g. Canada) or public health insurance would be considered centrist, and the regulated private healthcare just passed would be a right-wing proposal.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-4969117541894567273?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/4969117541894567273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=4969117541894567273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/4969117541894567273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/4969117541894567273'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2010/03/ive-been-watching-usa-healthcare-fiasco.html' title='the old man and the cspan'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-932466875753059238</id><published>2009-11-17T01:20:00.005+13:00</published><updated>2009-11-17T01:55:15.864+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='encoding'/><category scheme='http://www.blogger.com/atom/ns#' term='unicode'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>what encoding is that?</title><content type='html'>&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/_exDwNmaRSoc/SwFHNOXb1UI/AAAAAAAAAEk/CD4vyn7elsc/s1600/eclair.png"&gt;&lt;img style="float:right;" src="http://3.bp.blogspot.com/_exDwNmaRSoc/SwFHNOXb1UI/AAAAAAAAAEk/CD4vyn7elsc/s320/eclair.png" /&gt;&lt;/a&gt;

A few times in a project I'm working on, I've got some binary data that represents encoded text in some unknown encoding. Sometimes I know what it should decode to, and sometimes not.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://abstractable.net/encodingtools"&gt;Encoding Tools&lt;/a&gt; is a small application that decodes a byte string in a bunch of ways, and tries to guess which is correct.&lt;/p&gt;

&lt;p&gt;It runs on Mac OS X 10.5 or later, and the source is available from the link above.&lt;/p&gt;

&lt;p&gt;Hadn't used "real" Cocoa (as opposed to Touch) in a while, so this was a good excuse to play with Bindings and NSTokenField.&lt;br /&gt;
The former is very cool, but not quite as seamless as I thought - you get your UI and model synced without writing any extra code, as long as you do things in a KVO-compliant way, which requires writing &lt;a href="http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/CocoaBindings/Concepts/Troubleshooting.html#//apple_ref/doc/uid/TP40002148-182809"&gt;non-idiomatic extra code&lt;/a&gt;.&lt;br /&gt;
NSTokenField would be nice if it wasn't &lt;a href="http://lists.apple.com/archives/Cocoa-dev//2008/Feb/msg01089.html"&gt;broken&lt;/a&gt; by default.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-932466875753059238?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/932466875753059238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=932466875753059238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/932466875753059238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/932466875753059238'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2009/11/what-encoding-is-that.html' title='what encoding is that?'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_exDwNmaRSoc/SwFHNOXb1UI/AAAAAAAAAEk/CD4vyn7elsc/s72-c/eclair.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-7728759752113196846</id><published>2009-08-30T11:45:00.005+12:00</published><updated>2009-09-28T17:56:39.252+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='statistics'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><title type='text'>in which I actually write some software</title><content type='html'>&lt;img style="float:right;" src="http://abstractable.net/biocalc/images/screens/main.png" alt="BioCalc main screen" /&gt;
&lt;p&gt;&lt;a href="http://abstractable.net/biocalc/"&gt;Biostats Calculator&lt;/a&gt; appeared on the iTunes App Store the other day, after an approval process that felt like it took years (but actually was only a couple of weeks). It's my first iPhone app so it's kind of exciting, and some have been sold already (Hi, Colombia!), which is really exciting in the paying-my-rent kind of way.&lt;/p&gt;
&lt;p&gt;The application performs various biostatistical significance tests - relative risks, t-tests, chi-squared etc - and a couple of other calculations. (Full details are on the website). It aims to provide the most common statistical calculations a medical researcher might need, without having to go back to their computer and deal with a full statistics package. Also, it's totally awesome and you should &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325068885&amp;mt=8"&gt;buy it&lt;/a&gt; and tell your friends.&lt;/p&gt;
&lt;p&gt;&amp;lt;/plug&amp;gt;&lt;/p&gt;
&lt;p&gt;Other notes:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Objective C is awesome. Garbage collection is disabled on the iPhone, which I thought would bother me but is actually hardly a problem at all. It really gives you a sense of how simple the language as an extension of C - basically just objc_msgSend and a little bit of preprocessor magic. And knowing how the OO constructs work allows me to feel completely comfortable mixing in plain C instead when it's more natural. (I'm still not sure how autorelease works. I'm pretty sure it's magic.)&lt;/li&gt;
&lt;li&gt;Apple did a really good job on Cocoa Touch. The simple things seem to just work, and the hard things aren't all that hard. Except where they're impossible by design, per the next point.&lt;/li&gt;
&lt;li&gt;They're serious about their &lt;a href="http://developer.apple.com/iphone/library/documentation/userexperience/conceptual/mobilehig/Introduction/Introduction.html"&gt;Human interface guidelines&lt;/a&gt;. The first submitted version of the application used an 'add contact' button icon (rendered as a blue plus-sign) to add data to a data set, and they rejected it for misusing a standard icon. I took a screenshot of the button, tinted the image green, and they had no problem with that.&lt;/li&gt;
&lt;li&gt;The approval process is frustating. They have an actual human test your application, make sure it doesn't crash, follows guidelines, and does what it says on the box. I think this is a really good thing that drives up application quality and platform consistency, but it means waiting a couple of weeks between finishing the app and it hitting the store. Plus you get to repeat the whole process when you didn't read the HIG and used the wrong button icon. Ahem.&lt;/li&gt;
&lt;li&gt;Despite not being quite as streamlined a process as I would have assumed (lots of forms to fill out, certificates to download, having to get a credit card in my name to open an account, etc) the App Store is an amazing service. You develop the software, describe it, and decide how much it should cost, and that's it - you don't have to work out &lt;b&gt;how&lt;/b&gt; to sell it, just what the next app will do.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-7728759752113196846?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/7728759752113196846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=7728759752113196846' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7728759752113196846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7728759752113196846'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2009/08/in-which-i-actually-write-some-software.html' title='in which I actually write some software'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2028511633853377366</id><published>2009-05-14T06:24:00.005+12:00</published><updated>2009-08-30T17:03:10.017+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='guitar hero'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='usb'/><title type='text'>Enjoy - a JoyToKey clone for mac</title><content type='html'>&lt;p&gt;&lt;a href="http://www.electracode.com/4/joy2key/JoyToKey%20English%20Version.htm"&gt;JoyToKey&lt;/a&gt; lets you map joysticks to keyboard buttons to control programs that aren't joystick-aware. &lt;a href="http://www.carvware.com/gamepadcompanion.html"&gt;Gamepad Companion&lt;/a&gt; is a similar thing for Mac but it's nagware and it annoyed me. Also I wanted the ability to automatically switch configurations depending on the active application. So: &lt;a href="http://abstractable.net/enjoy/"&gt;Enjoy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Somewhat related: &lt;a href="http://abstractable/misc/gh_tilt.c"&gt;half-working hack&lt;/a&gt; to get the tilt-sensor on a generic PS3 guitar hero controller to work with &lt;a href="http://fretsonfire.sourceforge.net/"&gt;Frets on Fire&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2028511633853377366?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2028511633853377366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2028511633853377366' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2028511633853377366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2028511633853377366'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2009/05/enjoy-joytokey-clone-for-mac.html' title='Enjoy - a JoyToKey clone for mac'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-1164531647940478035</id><published>2009-03-03T00:23:00.006+13:00</published><updated>2009-03-03T14:45:02.803+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='poker'/><category scheme='http://www.blogger.com/atom/ns#' term='game theory'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>poker paradox?</title><content type='html'>&lt;h2&gt;hold'em in a nutshell&lt;/h2&gt;
&lt;p&gt;Each player has 2 secret cards, and later 5 shared cards are revealed. Players bet on who has the best combination of cards both before and after the shared cards are revealed. Most secret cards are not worth betting on, good players will play between 10% and 30% of their hands.&lt;/p&gt;
&lt;h2&gt;three common principles&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Deception (&lt;a href="http://en.wikipedia.org/wiki/Fundamental_theorem_of_poker"&gt;fundamental theorem of poker&lt;/a&gt;): if your opponent has less (or wrong) information, you make more money than if they have more information&lt;/li&gt;
&lt;li&gt;Hand strength: all else equal, you make more money with higher cards than lower cards. (E.g. 9♣8♣ vs 8♣7♣)&lt;/li&gt;
&lt;li&gt;Style: a range of styles can be equally profitable, for example you may be able to maximise your winnings by playing anything from 10% to 30% of hands.&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;the problem&lt;/h2&gt;
&lt;p&gt;These principles seem axiomatic (except perhaps the third, but empirically it seems true). But they conflict:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Take two optimal strategies: a tight 10%-of-hands game "A" and a loose 30% game "B".&lt;/li&gt;
&lt;li&gt;At the start of each hand, flip a coin, and play either strategy "A" or "B" accordingly. Call this compound strategy "C".&lt;/li&gt;
&lt;li&gt;A player who's played against either A or B for long enough knows they play 10% or 30% of hands respectively, and they're winning so it's probably the best 10% or 30% of hands. (Strictly, &lt;b&gt;a&lt;/b&gt; best 10%. Hand strength is only a partial order, it doesn't compare 9♣8♣ to 2♢2♠).&lt;/li&gt;
&lt;li&gt;A player who's played against C knows that he plays 20% of hands. If the player is very observant he might know about the coin-flipping, but if the coin is hidden he doesn't know whether he's playing against A or B for a particular hand. In either case, he's playing against an optimal strategy with less information than last time, so when the coin comes up heads C makes more money than A, and when it comes up tails C makes more money than B. So C is more profitable than A and B (which were supposed to be equal and optimal).&lt;/li&gt;
&lt;li&gt;Strategy C involves sometimes playing hands in the 20-30th percentile, and sometimes &lt;b&gt;not&lt;/b&gt; playing hands in the 10-20th percentile. According to hand strength, we'd make more money by replacing some worse hands we're playing with some better ones we're not playing. This gives a strategy "D" where we flip a coin play the top 20% of hands according to strategy A or B.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So D &gt; C &gt; A and B, but A and B were supposedly optimal.&lt;/p&gt;
&lt;h2&gt;resolutions&lt;/h2&gt;
&lt;p&gt;The first weakness I can see is the assumption that it's always incorrect to throw away a more profitable and play a less profitable one. A hand like 5♡7♡ that rarely wins may be profitable if played occasionally because when it does win your opponent will discount the possibility that you have it. However you have to fold it most of the time, even though playing it would be profitable for that individual hand, to maintain this value.&lt;/p&gt;
&lt;p&gt;I'm surprised that the benefit from playing a probabilistic strategy is big enough to counteract the 'paradox'. Most analysis online tends to focus on opponent ranges - the range of cards they might have based on their actions in the hand - and it's assumed in calculations that the opponent would play their cards that way every time. Against good opponents, the edges of the ranges will be significantly fuzzy, and not accounting for this makes for flawed analysis that loses money (fundamental theorem again).&lt;/p&gt;
&lt;p&gt;The second weakness (thanks Kyle!) is the assumption that C gives our opponent less information than A or B. This is intuitively true if A and B are deterministic, in the same way that a coin-flip is more uncertain than 'heads' or 'tails' individually; but if they A and B are probabilistic then C may be no more uncertain - the average of two random numbers is not 'more random'.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-1164531647940478035?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/1164531647940478035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=1164531647940478035' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1164531647940478035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1164531647940478035'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2009/03/poker-paradox.html' title='poker paradox?'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-8676005901705657569</id><published>2009-01-26T01:37:00.012+13:00</published><updated>2009-01-26T05:18:17.708+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='game theory'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>guessing games 1</title><content type='html'>&lt;p&gt;One of the first programs I ever wrote was a number guessing game:&lt;/p&gt;
&lt;pre style="color:white;background-color:#080;padding:0.5em;width:50%;"&gt;I'M THINKING OF A NUMBER BETWEEN 1 AND 20
&gt; &lt;b&gt;7&lt;/b&gt;
HIGHER
&gt; &lt;b&gt;15&lt;/b&gt;
HIGHER
&gt; &lt;b&gt;18&lt;/b&gt;
LOWER
&gt; &lt;b&gt;17&lt;/b&gt;
YOU WIN&lt;/pre&gt;
&lt;p&gt;(The Commodore 64's green was brighter of course, but I wouldn't do that to you). The best strategy for beating the game, of course, is to pick the middle number of the range first in order to break the range in half. If that didn't happen to be the right number, you have a new possible range that's half the size, and you repeat the process. This is &lt;a href="http://en.wikipedia.org/wiki/Binary_search"&gt;binary search&lt;/a&gt; at its purest. It's the best strategy in two ways: it always finishes in at most 5 guesses (worst-case performance), and the average number of guesses needed if you pick randomly is 3.7 (average-case performance).&lt;/p&gt;
&lt;p&gt;I tried to write a program to do the guessing, but I couldn't work out how to let the user type "higher" or "lower" instead of numbers, and I gave up.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://1.bp.blogspot.com/_exDwNmaRSoc/SXxm09t36nI/AAAAAAAAADk/pQB14vbeO2E/s320/bsearch.png"  /&gt;&lt;/p&gt;
&lt;h2&gt;twenty questions&lt;/h2&gt;
&lt;p&gt;It's the same game, except instead of a number you can pick anything, and the guesser is allowed twenty yes-or-no questions to try to work out what it is.&lt;/p&gt;
&lt;pre style="color:white;background-color:#080;padding:0.5em;width:80%;"&gt;I'M THINKING OF A SOMETHING
&gt; &lt;b&gt;IS IT ORGANIC?&lt;/b&gt;
YES
&gt; &lt;b&gt;IS IT ALIVE?&lt;/b&gt;
YES
&gt; &lt;b&gt;IS IT A PLANT OR AN ANIMAL?&lt;/b&gt;
YES
&gt; &lt;b&gt;LOL, IS IT A PLANT XOR AN ANIMAL?&lt;/b&gt;
NO
&gt; &lt;b&gt;IS IT ROBERT PLANT?&lt;/b&gt;
YOU WIN&lt;/pre&gt;
&lt;p&gt;Obviously it wouldn't be an easy program to write, but in theory it's possible if we formalise the game. First we need a dictionary, a list of all the possible objects the computer can be thinking about. There can only be a finite number if we want the game to be winnable. &lt;/p&gt;
&lt;p&gt;Next we need a set of questions. Every yes-or-no question breaks the dictionary up into two sets: things that answer 'yes' and things that answer 'no'. We can characterise all questions by the sets of things that answer 'yes' (the objects they &lt;i&gt;accept&lt;/i&gt;). Two questions that accept the same objects are really the same question.&lt;/p&gt;
&lt;p&gt;Suppose our dictionary is {barrel, cat, dog, ball, fish, box, building}. The question "is it an animal?" accepts the objects {cat, dog, fish}. It's the same question, for our purposes, as "is it a cat or a dog or a fish" or "does it not begin with b".&lt;/p&gt;
&lt;p&gt;If we allow any question (that is, any set of objects) to be asked, then the game becomes trivial: we can reduce it to the number guessing game. Just number all the objects, break them into ranges, and ask questions like: "Is it barrel or cat or dog". This is the optimal strategy, which implies that you can't always win at twenty questions if there are more than a million possible answers. But it makes for long and boring questions, so in the informal game we might say you're only allowed twenty words per question. In the formal game we'll say you're provided with a list of questions you're allowed to ask. &lt;/p&gt;
&lt;p&gt;So our dictionary might be: {barrel, cat, dog, ball, fish, box, building}. And our questions might be:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;{cat, dog, fish} ("is it an animal?")&lt;/li&gt;
&lt;li&gt;{cat, dog, ball, &lt;a href="http://en.wikiquote.org/wiki/The_Simpsons#Rosebud_.5B5.04.5D"&gt;box&lt;/a&gt;} ("can you play with it?")&lt;/li&gt;
&lt;li&gt;{barrel, ball, box, building} ("does it begin with b?")&lt;/li&gt;
&lt;li&gt;{barrel} ("is it a barrel?")&lt;/li&gt;
&lt;li&gt;{cat} ("is it a cat?)&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The "is it a X" questions aren't strictly required, you could say you 'win' as soon as you know exactly what the object is. They do guarantee it's possible to win though.&lt;/p&gt;
&lt;p&gt;A strategy for 20 questions is a tree flowchart like the one for the guess-the-numbers game. Here's one for a poor strategy: just guessing.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://3.bp.blogspot.com/_exDwNmaRSoc/SXx0G7h5giI/AAAAAAAAAD0/b6wtzCpMtVc/s320/dumb_bsearch.png" /&gt;&lt;/p&gt;
&lt;p&gt;The height of the tree is 6 which indicates it may take us six guesses to work out the object in the worst case. This next one is better (height 3). In fact it's optimal: since it is as good as binary search we know there is no better strategy. Usually the optimal strategy won't be as good as binary search.&lt;/p&gt;
&lt;p&gt;&lt;img  src="http://1.bp.blogspot.com/_exDwNmaRSoc/SXx3cqvEqoI/AAAAAAAAAD8/kqp-mtaxIPk/s320/better_bsearch.png" /&gt;&lt;/p&gt;
&lt;p&gt;The question is: how do we efficiently calculate the optimal strategy? Either on the fly - i.e. given the information we have so far, determine the next question to ask - or by pre-computing the entire flowchart.&lt;/p&gt;
&lt;p&gt;More formally: given a set S and a collection of subsets T ⊆ ℘(S), construct a binary tree with leaves S and internal vertices T of minimal height, such that every left-descendant of t is in t, and no right-descendant is.&lt;/p&gt;
&lt;p&gt;An obvious heuristic, reminiscent of binary search, is to always ask a question that splits the remaining possibilities as close to evenly as possible. While we might expect that this 'greedy algorithm' is optimal, it isn't due to interactions between questions. In the diagram below, question A divides the space of objects neatly in half, but whatever question we ask next we can be left with around a third of the objects afterward. Starting with questions B and C guarantees only a little more than a quarter of the possibilities remain after two questions.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://4.bp.blogspot.com/_exDwNmaRSoc/SXyI0qvTGHI/AAAAAAAAAEE/QLeYOxxxtfI/s320/pie.png" /&gt;&lt;/p&gt;
&lt;p&gt;A naive but approach is to recursively find the best left and right subtrees for the subsets induced by each first question, and choose the question that gives minimal max-height. Ultimately this runs takes exponential time since we find the tree for all 2&lt;sup&gt;n&lt;/sup&gt; subsets of the dictionary. It has the feel of a hard problem, I wonder if exponential time is the best possible.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-8676005901705657569?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/8676005901705657569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=8676005901705657569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/8676005901705657569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/8676005901705657569'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2009/01/guessing-games-1.html' title='guessing games 1'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_exDwNmaRSoc/SXxm09t36nI/AAAAAAAAADk/pQB14vbeO2E/s72-c/bsearch.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2436023377528161276</id><published>2008-11-16T00:52:00.002+13:00</published><updated>2008-11-16T00:55:17.139+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comic'/><title type='text'>and you shall know a webcomic by the questions he (frequently) answers</title><content type='html'>&lt;p&gt;&lt;a href="http://www.amazingsuperpowers.com/"&gt;Amazing Super Powers&lt;/a&gt; is still funny when sober? Signs point to yes.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.amazingsuperpowers.com/ComicArchive/098.htm"&gt;&lt;img src="http://www.amazingsuperpowers.com/COMICdocknife.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2436023377528161276?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2436023377528161276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2436023377528161276' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2436023377528161276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2436023377528161276'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2008/11/and-you-shall-know-webcomic-by.html' title='and you shall know a webcomic by the questions he (frequently) answers'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-3564158218632467557</id><published>2008-11-11T17:43:00.002+13:00</published><updated>2008-11-11T18:17:20.532+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='statistics'/><category scheme='http://www.blogger.com/atom/ns#' term='puzzle'/><category scheme='http://www.blogger.com/atom/ns#' term='game theory'/><title type='text'>on envelopes</title><content type='html'>&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Two_envelopes_problem"&gt;The two-envelopes&lt;/a&gt; problem, via xkcd. I'm not goint to re-hash it here, because it makes me dizzy, and the wikipedia page is fine. It's a 'paradox' of probability/game theory - like &lt;a href="http://en.wikipedia.org/wiki/Monty_Hall_problem"&gt;Monty Hall problem&lt;/a&gt; but without goats, cars, or a convincing solution.&lt;/p&gt;
&lt;p&gt;There doesn't seem to be any dispute that if you can take a 50-50 bet that will either double or halve your money, then you should - your average profit is 25%. On the other hand, looking in your envelope doesn't give you any useful information, and switching without looking can't possibly earn you money in the long run. So what's going on?&lt;/p&gt;
&lt;p&gt;Clearly the odds bet isn't 50-50! And the problem is that in order to fill the envelopes, we have to randomly pick an amount of money $X to put in the small envelope. But what does random mean? We can't have a &lt;b&gt;uniform&lt;/b&gt; distribution over an infinite range - it doesn't make sense. You're trying to pick a number at random between 1 and infinity, whatever you pick will be in the bottom 1%.&lt;/p&gt;
&lt;p&gt;Once we look in the envelope and see $Y, we know X = Y or X = Y/2. It's only a 50-50 bet if those possibilities are equally likely, and there aren't any probability distributions that have P(Y) = P(Y/2) for all Y. &lt;/p&gt;
&lt;p&gt;So the game, as stated, can never be played. Any real randomizer for the game is going to give the player worse than 50-50 odds in some cases, and they won't make profit by switching in the long run.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-3564158218632467557?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/3564158218632467557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=3564158218632467557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3564158218632467557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3564158218632467557'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2008/11/on-envelopes.html' title='on envelopes'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2944015914051634335</id><published>2008-11-10T10:29:00.005+13:00</published><updated>2008-11-10T12:10:03.417+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='election'/><category scheme='http://www.blogger.com/atom/ns#' term='mmp'/><category scheme='http://www.blogger.com/atom/ns#' term='government'/><title type='text'>that other election</title><content type='html'>&lt;p&gt;So New Zealand just had &lt;a href="http://2008.electionresults.govt.nz/partystatus.html"&gt;our election&lt;/a&gt;. My take on the results: disappointing, not surprising, and not the end of the world. &lt;/p&gt;
&lt;p&gt;The process was pretty uneventful compared to &lt;a href="http://blog.ourvotelive.org/?m=20081104"&gt;certain recent elections&lt;/a&gt;. Most of the difference can, I think, be attributed to a less polarised political culture; but part is the proportional representation system that prevents some votes being worth much more than others according to which part of the country you live in. The importance of a few 'swing' states (Ohio, Florida, et al) makes it tempting to try to tip the scales, and the rush of attention, money, and pressure to them provides the opportunity. If every vote is worth the same, election fever is spread out and doesn't boil over. (You like that metaphor? I mixed it myself).&lt;/p&gt;
&lt;h2&gt;mmp is broken&lt;/h2&gt;
&lt;p&gt;But we don't quite use proportional representation. New Zealand's system gives everyone a vote for a party, and a vote for a local MP. The party votes decide the proportional makeup of the parties in parliament. The electorate votes decide who your 'local MP' is. This is a carry-over from our old system where a parliament was made up of all the local MPs. &lt;/p&gt;
&lt;p&gt;The upshot is that if the Banana party wins half the votes, they get 60 seats (out of 120) to fill with bananas. If Alice, Bob, and Carol from the Banana party all won local seats, then they have to be included. The other 57 seats are filled from a party list.&lt;/p&gt;
&lt;p&gt;But there's a situation called 'overhang' that happens when a party wins too many electoral seats. Suppose the Banana party wins 65 electorates - more seats than their proportional fair share. What happens is 5 extra seats are created, so parliament has 125 instead of 120. All the electorate MPs are seated, and of course they don't get any list MPs. The proportionality has been distorted - the party with 50% of the vote got 52% of the seats.&lt;/p&gt;
&lt;p&gt;This is pretty much impossible, there are only 70 electorate seats and to win that many without getting more than 50% of the vote isn't going to happen. But it can happen with smaller parties, in particular those with regional appeal. In our last election in 2005, we had an overhang for the first time. The Maori party won 4 electorate seats, but only had 3 seats worth of party vote. &lt;/p&gt;
&lt;h2&gt;and getting worse&lt;/h2&gt;
&lt;p&gt;This time around they got 5 electorate seats with basically the same party vote, creating an overhang of two seats. So far, so slightly odd. Now I'm going to do something very odd and assume both politicians and voters are rational.&lt;/p&gt;
&lt;p&gt;Suppose you're a Maori party supporter. You know they tend to win more electorate seats than their party share. If you give them your party vote, you're not going to increase the number of seats they get, you're just going to decrease the size of their overhang by one. This increases their power a little (5/121 seats beats 5/122) but not much. Suppose they have a naturally allied party that doesn't have an overhang. You're better off giving that party your party vote, to better increase the size of your bloc and therefore the chances Maori make it into a coalition government.&lt;/p&gt;
&lt;p&gt;Now suppose you're the Maori party. You realise this vote-splitting is better for you too, so you put out a TV ad directing supporters to vote that way. The Maori party vote drops to almost zero, they have the same number of seats, and more powerful allies. &lt;/p&gt;
&lt;p&gt;If you're the allied party, you realise that running local candidates helps your profile a bit, but doesn't actually increase your share of parliamentary power. The Maori party winning electoral seats does help you, though, because it increases your voting bloc. So you stop running electoral candidates against them, and possibly encourage your popular local candidates to switch parties.&lt;/p&gt;
&lt;p&gt;So given two allied parties, once one achieves an overhang, rational behavior leads to one becoming completely electorate-based, and one completely party-based. We have two single-seat parties in parliament at the moment, although both got enough party votes to 'cover' their electoral seat and avoid overhang. I think at least Jim Anderton may explicitly aim for an overhang next time, effectively running as an independent.&lt;/p&gt;
&lt;h2&gt;major parties?&lt;/h2&gt;
&lt;p&gt;Could a major party split in half to achieve the same thing? There are some practical problems:
&lt;ul&gt;&lt;li&gt;You can't give list seats to people if they lose their electorate, if they're not in the same party. You'd probably just want to split off the party's 'safe' seats.&lt;/li&gt;
&lt;li&gt;People will see it as cheating, and react negatively. A minor party has less choice, and more dedicated supporters, so can get away with gaming the system. A major party is likely to suffer blowback. However once one party succeeds with it, the others need to follow suit to be competitive.&lt;/li&gt;
&lt;li&gt;You'd lose some support just due to the confusion - we're assuming rational and informed voters, but not everyone's going to split their vote in the desired way. For example, they might vote for the 'electorate' party.&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;If a major party did this the rules would almost certainly be changed quickly. The temptation is great, though - splitting your supporters' electorate votes to an overhang party increases its power by around 57%, and not taking advantage of this leaves votes on the table.&lt;/p&gt;

&lt;h2&gt;solutions?&lt;/h2&gt;
&lt;p&gt;Wikipedia discusses &lt;a href="http://en.wikipedia.org/wiki/Mixed_member_proportional_representation"&gt;forms of MMP&lt;/a&gt; without overhang seats. The only one that sounds unreasonable is a system used in some German states, where extra party seats are allocated to restore proportionality. Supposing a party won 0.1% of the vote and 1 electorate seat (which would no longer be strategically clever, but can easily happen). To restore proportionality you need to inflate parliament to 1000 members!&lt;/p&gt;
&lt;p&gt;My personal opinion is that sacrificing proportionality to provide strong voices to particular groups is misguided. If parliament can protect against injustice to minorities in general, then it can protect against injustice to certain parts of the country. (And if a parliament doesn't protect minorities from mob rule, it needs to be redesigned). If the need for advocacy is there and local governments aren't strong enough, perhaps the electorate vote could be changed to non-voting advocates to parliament.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2944015914051634335?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2944015914051634335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2944015914051634335' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2944015914051634335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2944015914051634335'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2008/11/that-other-election.html' title='that other election'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-748702427920921101</id><published>2008-10-27T09:18:00.009+13:00</published><updated>2008-10-27T10:48:16.826+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='colour'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>It's like looking into the eye of a duck</title><content type='html'>&lt;p&gt;If colour is a spectrum of frequencies from low to high, why does it form a circle? And why can we make it all up out of three 'primary' frequencies?&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;a href="http://www.j-a-b.net/web/hue/pics/hue_1a"&gt;&lt;img alt="color circle" src="http://3.bp.blogspot.com/_exDwNmaRSoc/SQTTARhLSGI/AAAAAAAAACg/EfznCtpJOw8/s400/hue_1a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5261562266331596898" /&gt;&lt;/a&gt; &lt;a href="http://www.astro.uiuc.edu/~kaler/arc/sk102105.html"&gt;&lt;img src="http://4.bp.blogspot.com/_exDwNmaRSoc/SQTVsauwDuI/AAAAAAAAAC4/ggLNAchixJE/s320/spectrum.jpg" alt="spectrum" /&gt;&lt;/a&gt; &lt;a href="http://denbeste.nu/external/triangle.jpg"&gt;&lt;img src="http://3.bp.blogspot.com/_exDwNmaRSoc/SQTWPC04InI/AAAAAAAAADA/uP1WmNwNHAU/s160/triangle.jpg" alt="rgb triangle" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I never quite got this, and this article on &lt;a href="http://www.mathpages.com/home/kmath578/kmath578.htm"&gt;Pitch and Color Recognition&lt;/a&gt; is a fascinating read.&lt;/p&gt;
&lt;p&gt;In short, our eyes have specific receptors ('cones') for red, green, and blue light. But they don't just pick up one particular frequency from the spectrum, they respond strongly to a small range of frequencies, with a bell-curve decay as the colour changes.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.mathpages.com/home/kmath578/kmath578.htm"&gt;&lt;img src="http://4.bp.blogspot.com/_exDwNmaRSoc/SQTaSqv7OPI/AAAAAAAAADI/k1k0uv-FTfs/s320/image010.gif" alt="frequency vs response" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The odd-one-out is the red receptor, which starts to trigger &lt;i&gt;again&lt;/i&gt; at low frequencies (violet). The perceived 'hue' is determined by the ratio of the responses, which is similar at low and high frequencies, thus the cycle.&lt;/p&gt;
&lt;p&gt;Now if you work your way through the spectrum, measuring the response to pure monochromatic light of each colour, you get the blue horseshoe path in this diagram which I had often seen but never understood.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://1.bp.blogspot.com/_exDwNmaRSoc/SQTRFnY0rwI/AAAAAAAAACY/Jm8EkWFwpqc/s400/image015.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5261560159078231810" /&gt;&lt;/p&gt;
&lt;p&gt;X is full red response with nothing else, Y is full green response, and Z is full blue response. Note that no pure frequency of light can get this response - there's no point on the previous graph where only one receptor responds.&lt;/p&gt;
&lt;p&gt;If you mix two colours together, the responses get added together (that is, averaged) so the response lies inside the horseshoe. So the horseshoe contains all the colours that we could observe in the physical world. What do the points outside, such as X, Y, and Z represent? &lt;b&gt;There are 'colours', which we are biologically capable of perceiving, that don't exist in the real world.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;As for the RGB colour triangle - it's an approximation. Mixing light from the three points labeled R, G, and B can achieve any colour inside the triangle they form. &lt;b&gt;The small area outside the triangle but inside the horseshoe contains colours that occur (rarely) in nature, and cannot be accurately displayed on a monitor or television&lt;/b&gt;. Adding more primary colours is limited help - they have to be actual frequencies of light, so they lie on the horseshoe and approximate it with a polygon. You can never represent all colours by mixing a finite number together, although you can get arbitrarily close.&lt;/p&gt;
&lt;p&gt;There's so much more in the &lt;a href="http://www.mathpages.com/home/kmath578/kmath578.htm"&gt;article&lt;/a&gt; though...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-748702427920921101?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/748702427920921101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=748702427920921101' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/748702427920921101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/748702427920921101'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2008/10/its-like-looking-into-eye-of-duck.html' title='It&apos;s like looking into the eye of a duck'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_exDwNmaRSoc/SQTTARhLSGI/AAAAAAAAACg/EfznCtpJOw8/s72-c/hue_1a.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-1854846547656828732</id><published>2008-10-02T16:55:00.005+13:00</published><updated>2008-10-02T22:06:34.271+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comic'/><title type='text'>interviews</title><content type='html'>&lt;img src="http://2.bp.blogspot.com/_exDwNmaRSoc/SOSNfW26SBI/AAAAAAAAAB8/KF8GoCItGr8/s800/ten_years.png" alt="And where do you see yourself in ten years?" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-1854846547656828732?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/1854846547656828732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=1854846547656828732' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1854846547656828732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1854846547656828732'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2008/10/interviews.html' title='interviews'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_exDwNmaRSoc/SOSNfW26SBI/AAAAAAAAAB8/KF8GoCItGr8/s72-c/ten_years.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-1770903665109449841</id><published>2007-11-30T03:05:00.000+13:00</published><updated>2007-11-30T03:14:59.000+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='discursive'/><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>discursive</title><content type='html'>&lt;p&gt;Am I discussing something, swearing at you, or just writing in a way that's painful and difficult to read? Actually, all of the above. But what it really means is &lt;b&gt;off-topic rant&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Blog is still a fucking ugly word, is it too late to elect a new one?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-1770903665109449841?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/1770903665109449841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=1770903665109449841' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1770903665109449841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1770903665109449841'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/discursive.html' title='discursive'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-44129005281265382</id><published>2007-11-28T09:52:00.000+13:00</published><updated>2007-11-30T03:23:47.730+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dynamic'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='static'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='es4'/><title type='text'>static typing gets a bad rap</title><content type='html'>&lt;p&gt;&lt;a href="http://nothinghappens.net/?p=222"&gt;it’s not necessarily about dynamic languages&lt;/a&gt; - Chuck Hoffman draws nicely the distinction between the enterprisey static-typers and the academic static-typers. Java vs ML, if you will.&lt;/p&gt;

&lt;p&gt;The fact that you write&lt;/p&gt;
&lt;pre class="code"&gt;new JButton(new AbstractAction("test") {
  public void actionPerformed(ActionEvent e) {
    System.out.println("hi!");
  }
});&lt;/pre&gt;
&lt;p&gt;has little to do with static typing and everything to do with design philosophy. The language itself was supposed to be explicit and purely object-oriented, and the library aims to be extensible through abstraction. I'm sure those sounded like great ideas at some point.&lt;/p&gt;
&lt;p&gt;Equally viable, but not present in the "languages you can make money in" class, is&lt;/p&gt;
&lt;pre class="code"&gt;new JButton("test") {(e)
  println("hi")
}&lt;/pre&gt;
&lt;p&gt;Personally, I find static typing very useful in external APIs and mostly unhelpful elsewhere. While you gain rock-solid code completion and catch the occasional type error, you introduce new type errors - the 'compile-time types' that static analysis deals with can cause errors in otherwise correct code.&lt;/p&gt;
&lt;p&gt;So dynamic &lt;a href="http://www.ecmascript.org/"&gt;JavaScript 2&lt;/a&gt;'s optional type declarations seem preferable to &lt;a href="http://www.digitalmars.com/d/"&gt;D&lt;/a&gt; or &lt;a href="http://msdn2.microsoft.com/en-us/vcsharp/Aa336745.aspx"&gt;C# 3&lt;/a&gt;'s reduced-pain static type system, but it's not the religious issue for me that I thought it was.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-44129005281265382?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/44129005281265382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=44129005281265382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/44129005281265382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/44129005281265382'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/static-typing-gets-bad-rap.html' title='static typing gets a bad rap'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-3877227943471459946</id><published>2007-11-23T02:49:00.000+13:00</published><updated>2007-11-23T04:26:07.939+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>you know you're a nerd when...</title><content type='html'>&lt;p&gt;&lt;a href="http://bp1.blogger.com/_exDwNmaRSoc/R0WOq4hzQVI/AAAAAAAAAA0/2UqouYqiBNc/s1600-h/planarity_full.png"&gt;
&lt;img alt="gplanarity screenshot" src="http://bp0.blogger.com/_exDwNmaRSoc/R0WO0ohzQWI/AAAAAAAAAA8/7lVhnbSyVNA/" style="float:right;" /&gt;&lt;/a&gt;
... finding planar embeddings of graphs by hand is your idea of fun.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://planarity.net/"&gt;Planarity&lt;/a&gt; (flash) &lt;b&gt;is&lt;/b&gt; addictive though. You get a graph (a bunch of dots, some of the dots joined with lines), and have to move the dots around so that the lines don't cross.&lt;/p&gt;

&lt;p&gt;There's &lt;a href="http://en.wikipedia.org/wiki/F%C3%A1ry's_theorem"&gt;a theorem&lt;/a&gt; that says bending the lines doesn't help - if you can do it with curved lines, you can do it with straight lines.&lt;/p&gt;

&lt;p&gt;Some graphs can't be solved though. There's a superior (IMO) version for gnome called &lt;a href="http://web.mit.edu/xiphmont/Public/gPlanarity.html"&gt;gPlanarity&lt;/a&gt; that has 'no more than 4 crossings' type levels which are harder, and not just subjectively. There are efficient algorithms to &lt;a href="http://en.wikipedia.org/wiki/Planar_graph#Other_planarity_criteria"&gt;test for planarity&lt;/a&gt; and find embeddings, but for nonplanar graphs even determining the minimum crossing number is NP-hard.&lt;/p&gt;

&lt;p&gt;NP, of course, is the technical term for &lt;b&gt;very&lt;/b&gt;, because you need a technical term for everything. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-3877227943471459946?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/3877227943471459946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=3877227943471459946' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3877227943471459946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3877227943471459946'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/you-know-youre-nerd-when.html' title='you know you&apos;re a nerd when...'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-3886874440086718822</id><published>2007-11-21T22:24:00.000+13:00</published><updated>2007-11-22T12:40:25.400+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='bytecode'/><title type='text'>bytecode generation for fun and profiling</title><content type='html'>&lt;h3&gt;interfaces&lt;/h3&gt;
&lt;p&gt;An interface in Java is just a list of methods that can be implemented by classes. This lets you access objects of different classes in the same way, even if their implementation is unrelated.&lt;/p&gt;

&lt;p&gt;At least in principle, the interface is written first, and then the class references it:&lt;p&gt;
&lt;pre class="code"&gt;class Widget implements Drawable {&lt;/pre&gt;
&lt;p&gt;But to turn it around, you could define an interface as a subset of a class's methods, and use that to reduce coupling and allow calling code to be compiled without access to library code (common in J2EE). &lt;/p&gt;
&lt;p&gt;The problem is that the class has to be tagged &lt;code&gt;implements X&lt;/code&gt; at compile time.&lt;/p&gt;

&lt;h3&gt;example&lt;/h3&gt;
&lt;p&gt;I was working on a web-app and needed to set a parameter on an Oracle data source. I had a generic DataSource object, and the solution was to cast it to its real oracle.jdbc.pool.OracleDataSource and call the method. Three problems:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;I now have to include the oracle driver when I compile&lt;/li&gt;
&lt;li&gt;If a driver update or reconfiguration alters the class name, not only will my fix not work, but my &lt;code&gt;if(ds instanceof OracleDataSource)&lt;/code&gt; line will cause a crash&lt;/li&gt;
&lt;li&gt;This is pretty generally grungy just so i can call &lt;code&gt;setFoo(true)&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;These can be hacked around by using &lt;a href="http://java.sun.com/docs/books/tutorial/reflect/index.html"&gt;reflection&lt;/a&gt;, but it's ugly, not typesafe, and slow (less so these days).&lt;/p&gt;
&lt;p&gt;They can be fixed if the class implemented an interface which was provided in a separate jar, but it doesn't.&lt;/p&gt;

&lt;h3&gt;build a bridge and get over it&lt;/h3&gt;
&lt;pre class="code"&gt;public interface ToggleFoo { public void setFoo(boolean v); }

Bridge.expose(datasource, ToggleFoo.class).setFoo(true);&lt;/pre&gt;
&lt;p&gt;The Bridge utility creates a wrapper class like this:&lt;/p&gt;
&lt;pre class="code"&gt;public class Bridge_OracleDataSource_ToggleFoo implements ToggleFoo {
   private Object __target;
   public void setFoo(boolean v) {
      ((OracleDataSource)__target).setFoo(v);
   }
}&lt;/pre&gt;
&lt;p&gt;It then instantiates it and sets &lt;code&gt;__target&lt;/code&gt; to the object you pass. Since the wrapper is flagged as &lt;code&gt;implements ToggleFoo&lt;/code&gt;, the instance can be cast to ToggleFoo and returned.&lt;/p&gt;
&lt;p&gt;The class is generated at runtime using &lt;a href="http://jakarta.apache.org/bcel/"&gt;Apache BCEL&lt;/a&gt;. The compiled bytecode is created directly, without source code, and loaded using a custom ClassLoader.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;expose(Object, Class)&lt;/code&gt; is called (the Class object represents an interface), the library uses reflection to find the correct type to cast the object to. The same rules of visibility normally enforced by the compiler apply at the JVM level, so there has to be a public class/superclass that implements the methods in the interface.&lt;/p&gt;

&lt;h3&gt;subsetting interfaces&lt;/h3&gt;
&lt;p&gt;Another use is to convert from an interface type to a more restricted interface - a 'superinterface' that was never specified. For example:&lt;/p&gt;
&lt;pre class="code"&gt;public interface ImmutableList { 
   int size();
   Object get(int i);
}

ImmutableList lst = Bridge.expose(myArrayList, ImmutableList.class);&lt;/pre&gt;
&lt;p&gt;Now &lt;code&gt;lst&lt;/code&gt; can be securely passed to client code without fear of modification.&lt;/p&gt;

&lt;h3&gt;performance comparison&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Setup&lt;/b&gt;: When a type exposes a new interface, the bridge class must be generated and loaded. This is actually very fast (~5ms in my tests) but the first time requires BCEL to load, which took about 500ms. I haven't included this in tests below, it's important for short-running tasks.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Each object&lt;/b&gt;: calling &lt;code&gt;Bridge.expose()&lt;/code&gt; allocates a small new wrapper object, and sets a field in it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Each call&lt;/b&gt;: Calling a method through the interface requires an interface method call (slower than a normal virtual one), a field access, and a virtual method call to the target.&lt;/p&gt;

&lt;p&gt;The common alternatives to a bytecode generation approach are direct access and reflection.&lt;/p&gt;

&lt;p&gt;Direct access to the object is always going to be fastest, and it's important to know how much speed you're giving up for this decoupling, or security (in the case of subsetting an interface).
There is no setup, each object just has to be cast to the correct type, and calling is just a virtual method call.&lt;/p&gt;

&lt;p&gt;Reflection was optimised in Java 1.4, but is still carries a penalty.
&lt;code&gt;Class.getMethod()&lt;/code&gt; must be called for each new class of target. In my test all targets were in fact the same class (even the same instance) but the code did not assume it, so the fact that the class is the same has to be checked for each new object. 
You call the method with &lt;code&gt;Method.invoke()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;&lt;a name="timing"&gt;Timing results&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;tr&gt;&lt;th&gt;Test&lt;/th&gt;&lt;th&gt;Direct&lt;/th&gt;&lt;th&gt;Reflection&lt;/th&gt;&lt;th&gt;Bridge&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="left"&gt;Invoke virtual method on same object&lt;/th&gt;&lt;td&gt;68ms&lt;/td&gt;&lt;td&gt;2772ms&lt;/td&gt;&lt;td&gt;258ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="left"&gt;Invoke virtual method on different object&lt;/th&gt;&lt;td&gt;70ms&lt;/td&gt;&lt;td&gt;2808ms&lt;/td&gt;&lt;td&gt;5621ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="left"&gt;Invoke method through interface on same object&lt;/th&gt;&lt;td&gt;163ms&lt;/td&gt;&lt;td&gt;3384ms&lt;/td&gt;&lt;td&gt;237ms&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;b&gt;edit&lt;/b&gt;: improved performance by 30% on second test by removing an extra object allocation. Allocating objects in a tight loop is still slow.&lt;/p&gt;

&lt;p&gt;Testing was on Sun Java 1.5.0_11 i386 on Linux (Ubuntu 7.02), on my laptop (Athlon XP 1800+). &lt;a href="http://snippets.dzone.com/posts/show/4806"&gt;source&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;code&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://snippets.dzone.com/posts/show/4804"&gt;Is here&lt;/a&gt;. If it breaks, you keep both pieces. You need bcel.jar on your -classpath, from &lt;a href="http://jakarta.apache.org/site/downloads/downloads_bcel.cgi"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's &lt;a href="http://headius.blogspot.com/2007/11/bytecode-tools-in-ruby-low-level-dsl.html"&gt;a new library&lt;/a&gt; to generate JVM bytecode from ruby. I'm not so hot on JRuby, but this looks cool for learning the bytecode.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-3886874440086718822?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/3886874440086718822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=3886874440086718822' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3886874440086718822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3886874440086718822'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/bytecode-generation-for-fun-and.html' title='bytecode generation for fun and profiling'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2351264689757920362</id><published>2007-11-21T03:41:00.000+13:00</published><updated>2007-11-23T02:48:26.913+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='charity'/><category scheme='http://www.blogger.com/atom/ns#' term='advertising'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>save the world in 2 x 10^15 easy steps</title><content type='html'>&lt;p&gt;&lt;a href="http://freerice.com/index.php"&gt;FreeRice&lt;/a&gt; is distraction o' the day. The premise is you play a spot-the-synonym game and improve your vocabulary. There are ads on the page, and they claim to donate 10 grains of rice to charity for every question you get right. There's a counter on the side of the screen showing how 'generous' you are so far. There's no sign-up, and no restrictions on how long you play for.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://freerice.com/"&gt;&lt;img style="float:right;" src="http://freerice.com/images/freeRiceLogo.gif" alt="Free Rice" /&gt;&lt;/a&gt; Assuming they're being straight with us, my first thought is that the advertisers are getting fleeced. You load a new page (and new ads) with each answer, say every 30 seconds, and you're pretty intently focused on the middle of the screen. At 1024x768 (still on the laptop) the ads aren't even visible. 
I guess we're meant to be getting warm fuzzy feelings about the companies, but it seems more like a &lt;a href="http://www.wlug.org.nz/ZFree"&gt;clever hack&lt;/a&gt; than a business model.&lt;/p&gt;

&lt;p&gt;(Hmm, and they only pay out rice for correct answers. On the other hand I bet advertisers would pay double to be able to show ads to dumb people. I take it back, it's a brilliant strategy!)&lt;/p&gt;

&lt;p&gt;The game itself is addictive. Knowing what the words mean is a plus, of course, but you can do pretty well boggling at prefixes and suffixes and word roots (periphrasis = circumlocution was a striking example). &lt;br /&gt;
And the 'feeding poor children' angle takes the edge off the 'should have stopped ten minutes ago' guilt. Ignoring for the moment that it takes more than 10,000 correct answers to make up the equivalent of a $US100 donation. (&lt;a href="http://lancewiggs.com/2007/11/12/free-rice-addictive-but-is-it-a-scam/"&gt;Figures from here&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;american politics never fails to deliver&lt;/h3&gt;
&lt;p&gt;Check this out. Words fail me.&lt;/p&gt;
&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/EjYv2YW6azE&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/EjYv2YW6azE&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=EjYv2YW6azE"&gt;HuckChuckFacts @ YouTube&lt;/a&gt; - Mike Huckabee's first campaign ad.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;edit&lt;/b&gt;: it's official - &lt;a href="http://www.mikehuckabee.com/index.cfm?FuseAction=Newsroom.PressRelease&amp;ID=383"&gt;Ric Flair: "Mike Huckabee is the Man, Whooooo!"&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2351264689757920362?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2351264689757920362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2351264689757920362' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2351264689757920362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2351264689757920362'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/save-world-in-2-x-1015-easy-steps.html' title='save the world in 2 x 10^15 easy steps'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-7047354373307648254</id><published>2007-11-18T18:56:00.000+13:00</published><updated>2007-11-22T01:33:07.875+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='tv'/><category scheme='http://www.blogger.com/atom/ns#' term='web'/><title type='text'>uninteresting and non-technical</title><content type='html'>&lt;p&gt;So much for '&lt;a href="http://timsuth.tumblr.com/post/19524897"&gt;interesting technical stuff&lt;/a&gt;'... They took the Daily Show clips off YouTube so I wrote a &lt;a href="http://snippets.dzone.com/posts/show/4794"&gt;script&lt;/a&gt; to pull them off the &lt;a href="http://www.thedailyshow.com/"&gt;official website&lt;/a&gt;, making a couple of cogent points.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;I need a bigger hard drive. Okay, this was the only one I'd call cogent.&lt;/li&gt;
&lt;li&gt;Using DRM to stop people from archiving free content wouldn't be totally ineffective. If they'd so much as bothered to gzip the &lt;a href="http://www.comedycentral.com/sitewide/video_player/shared/data/flv_xml_gen.jhtml?ml_video=115901&amp;hiLoPref=hi"&gt;xml descriptor&lt;/a&gt; that contains the download key for the video, I'd probably have missed it and lost interest. Someone smarter would still have found it, but they probably have better things to do.&lt;/li&gt;
&lt;li&gt;The result in my case would have just been not to bother watching it. It actually shows on TV here, but I've got a 50% attrition rate per ad-break - I'm easily distracted.&lt;/li&gt;
&lt;li&gt;Result for them: I don't watch any ads, I might buy some of the books of authors interviewed, or action figures of the actors or politicians. I doubt Comedy Central get any income that way. I cost them a bunch of bandwidth.&lt;/li&gt;
&lt;li&gt;Same on TV, but replace 'bandwidth' with 'broadcasting costs'.&lt;/li&gt;
&lt;li&gt;Same on YouTube, but replace 'broadcasting costs' with 'nothing'.&lt;/li&gt;
&lt;li&gt;Great programmers are meant to be lazy. I just spent Sunday watching TV shows using only my spacebar and my big toe. I hope it's a linear relationship.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-7047354373307648254?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/7047354373307648254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=7047354373307648254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7047354373307648254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/7047354373307648254'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/uninteresting-and-non-technical.html' title='uninteresting and non-technical'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-9040848511572916177</id><published>2007-11-15T03:55:00.000+13:00</published><updated>2007-11-22T01:32:42.028+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>analyse this</title><content type='html'>&lt;p&gt;&lt;a href="http://www.redmonk.com/jgovernor/2007/11/14/fireside-chats-suit-markets-as-conversations-on-microsofts-analyst-relations-program/"&gt;James Governor:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;Microsoft analyst relations (AR) has begun to use a format it is calling the fireside chat, in which a senior executive talks without PowerPoint to a select group of analysts.&lt;/blockquote&gt;
&lt;p&gt;What's it called when you present more clearly by throwing away the presentation software that you sell for a living? Oh yeah, innovation!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-9040848511572916177?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/9040848511572916177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=9040848511572916177' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/9040848511572916177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/9040848511572916177'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/analyse-this.html' title='analyse this'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-3804734948198239863</id><published>2007-11-15T01:24:00.000+13:00</published><updated>2007-11-22T01:32:10.847+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>restful robot</title><content type='html'>&lt;p&gt;Despite &lt;a href="http://robilad.livejournal.com/22312.html"&gt;licensing questions&lt;/a&gt; and &lt;a href="http://intertwingly.net/blog/2007/11/13/Gate"&gt;lock-in concerns&lt;/a&gt;, google's &lt;a href="http://code.google.com/android"&gt;android SDK&lt;/a&gt; is pretty damn exciting. &lt;/p&gt;

&lt;p&gt;For all the anti-hype about it not being a gPhone, the hardware wouldn't have been the cool part anyway. Google would rather be Microsoft than Dell, and the part of Apple has &lt;a href="http://www.apple.com/iphone/"&gt;already been cast.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading through the &lt;a href="http://code.google.com/android/documentation.html"&gt;documentation&lt;/a&gt; (and it's &lt;b&gt;good&lt;/b&gt;) shows they've had some smart people thinking hard about how applications should work. The appearance of the applications is your standard stack-of-screens, i.e. you can go back 'up' to the parent screen, but the way you implement them is different from desktop and J2ME applications and closer to web applications.&lt;/p&gt;

&lt;p&gt;Each screen type is called an &lt;a href="http://code.google.com/android/reference/android/app/Activity.html"&gt;Activity&lt;/a&gt;, and activities are well separated from each other. Instead of creating a screen by instantiating it and passing it a bunch of state directly, you identify an '&lt;a href="http://code.google.com/android/reference/android/content/Intent.html"&gt;intent&lt;/a&gt;' - a URI representing that state plus the action you want to perform, and pass it to android. For example: instead of creating a ViewContact, passing it a Contact object, you request to VIEW content://contacts/6. It's reminiscent of HTTP in a way that can't be coincidental.&lt;/p&gt;
&lt;p&gt;The URIs are managed by &lt;a href="http://code.google.com/android/reference/android/content/ContentProvider.html"&gt;ContentProvider&lt;/a&gt;s that serve as the model in your applications, and they have content types. Activities define which content-types, actions, and URIs they can handle and android selects the right one.&lt;/p&gt;

&lt;p&gt;This has lots of benefits for the ways applications work together. On the web, I can link to a photo on my friend's website, and they can change it from a JPEG to a PNG, or to a movie, or to a webpage with 20 photos, and the link still works.&lt;/p&gt;

&lt;p&gt;Most of the rules for android apps are actually guidelines - you can refer to activities explicitly, and you can pass more than a URI.  There are pragmatic reasons for tight coupling of internal components in some cases. But if applications play by the rules where functionality can be cleanly separated, web mashup type apps might make it to the phone.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-3804734948198239863?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/3804734948198239863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=3804734948198239863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3804734948198239863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3804734948198239863'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/restful-robot.html' title='restful robot'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-5253056757579979616</id><published>2007-11-13T02:44:00.000+13:00</published><updated>2007-11-22T01:52:20.262+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>tone generation in java</title><content type='html'>Frigging java. I claim to hate it and yet I can't resist being able to run in a browser.
Anyway, if there's an easy way to play a tone of an arbitrary pitch (not neccesarily on the MIDI scale) I couldn't find it. Here's some code for google.

Usage:
&lt;pre class="code"&gt;SineWave tune = new SineWave();
tune.play(440, 0.5); // C4 - frequency in hertz, duration in seconds
tune.play(554.4, 0.5); // E4 - play() blocks until the end of the note
tune.play(659.2, 0.5); // G4 - I'll probably do an async version later
tune.play(880, 1); // C5
tune.closeLine();&lt;/pre&gt;
&lt;a id="show_code_1" href="#" onclick="document.getElementById('code_1').style.display='';document.getElementById('show_code_1').style.display='none';document.getElementById('hide_code_1').style.display='';return false;"&gt;Show code&lt;/a&gt; &lt;a id="hide_code_1" href="#" onclick="document.getElementById('code_1').style.display='none';document.getElementById('show_code_1').style.display='';document.getElementById('hide_code_1').style.display='none';return false;" style="display:none;"&gt;Hide code&lt;/a&gt;
&lt;pre class="code" id="code_1" style="display:none;"&gt;// this code is in the public domain
import javax.sound.sampled.*;

public class SineWave {
 public static final float SAMPLE_RATE = 44100F;
 public static final int SAMPLE_SIZE = 16;
 public static final short MAGNITUDE = 0x7000;
 // 44.1 kHz 16-bit mono signed little-endian linear PCM
 AudioFormat format = new AudioFormat(SAMPLE_RATE, SAMPLE_SIZE, 1, true, false);
 SourceDataLine line;
 byte[] buf;
 int attackLength, decayLength;

 public SineWave() { this(0.01,0.01); }
 public SineWave(double attackTime, double decayTime){
  attackLength = (int)(attackTime * SAMPLE_RATE);
  decayLength = (int)(decayTime * SAMPLE_RATE);
 }

 private SourceDataLine getLine() {
  if(line == null) {
   DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
   try {
    line = (SourceDataLine)AudioSystem.getLine(info);
    line.open(format);
    line.start();
    buf = new byte[8192];
   } catch (LineUnavailableException e) {
    throw new RuntimeException(e);
   }
  }
  return line;
 }
 private void closeLine() {
  line.stop();
  line.close();
  line = null;
  buf = null;
 }

 public void play(double frequency, double seconds) {
  long max_sample = Long.MAX_VALUE;
  if(seconds &gt; 0)
   max_sample = (long)(seconds * SAMPLE_RATE);
  long position = 0;

  double signal;
  double multiplier = 2 * Math.PI * frequency / SAMPLE_RATE;
  short sample;
  int bufferPos;

  SourceDataLine line = getLine();

  while(position &lt; max_sample) {
   for(bufferPos = 0; position &lt; max_sample &amp;&amp; bufferPos &lt; buf.length; bufferPos += 2) {
    signal = MAGNITUDE * Math.sin(position * multiplier);

    // linear envelope at each end to avoid clicking
    if(position &lt; attackLength)
     signal *= (double)position/attackLength;
    if(position &gt; max_sample - decayLength)
     signal *= (double)(max_sample - position)/decayLength;

    sample = (short)signal;
    buf[bufferPos] = (byte)(sample &amp; 0x00ff);
    buf[bufferPos+1] = (byte)((sample &amp; 0xff00) &gt;&gt;&gt; 8);
    position++;
   }
   line.write(buf,0, bufferPos);
  }
 }
}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-5253056757579979616?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/5253056757579979616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=5253056757579979616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/5253056757579979616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/5253056757579979616'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/tone-generation-in-java.html' title='tone generation in java'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2962596755958944123</id><published>2007-11-12T13:57:00.000+13:00</published><updated>2007-11-22T01:31:09.436+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='politics'/><title type='text'>letters to the editor</title><content type='html'>&lt;p&gt;Just to prove I'm old. And because such &lt;a href="http://www.nzherald.co.nz/category/story.cfm?c_id=280&amp;objectid=10475416" title="Look, we can put a self-serving editorial on the front page instead of a story. Maybe we'll make the news!"&gt;unmitigated&lt;/a&gt; &lt;a href="http://www.nzherald.co.nz/category/story.cfm?c_id=280&amp;objectid=10475410" title="Some say too far, some say not far enough. See, compromise just makes people unhappy!"&gt;disingenuous&lt;/a&gt; &lt;a href="http://www.nzherald.co.nz/category/story.cfm?c_id=280&amp;objectid=10475414" title="Hard to draw a line between policy and politics? Not for us!"&gt;bullshit&lt;/a&gt; makes me too angry to even work out a rational opinion on the subject. &lt;/p&gt;

&lt;p&gt;Reproduced here &lt;s&gt;because I doubt they give the shit they say they give about speech.&lt;/s&gt;&lt;/p&gt;
&lt;blockquote cite="me"&gt;If the Herald is concerned that spending limits will impact free speech, it could start by halving the cost of all political advertisements. The primary beneficiaries of the saturation publicity race are the media outlets that sell the advertising. 
Domination of public awareness by big spenders is a threat, just as suppression of speech is. To present this as a one-sided moral issue is self-serving and irresponsible.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2962596755958944123?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2962596755958944123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2962596755958944123' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2962596755958944123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2962596755958944123'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/letters-to-editor.html' title='letters to the editor'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-9197256136364632347</id><published>2007-11-12T10:36:00.000+13:00</published><updated>2007-11-22T01:30:28.426+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>the sound of music</title><content type='html'>&lt;p&gt;Another year, another illusion shattered.&lt;/p&gt;

&lt;h3&gt;regale me with a story!&lt;/h3&gt;
&lt;p&gt;The thing that fascinated me about learning music, as a proto-geek (I gave up because I didn't have the discipline for practice) was the elegant way the scale fitted together. Playing in C major, G was clearly the next-best note - and G had its own scale, differing by just one note. D was the best note in that scale, and continuing in perfect 5ths took you all the way around - C G D A E B F# C#/Db Ab Eb Bb F C. &lt;/p&gt;

&lt;h3&gt;the radical antagonist&lt;/h3&gt;
&lt;p&gt;The pitches formed a nice pattern too - C&lt;sub&gt;4&lt;/sub&gt; (middle C) was half the frequency of C&lt;sub&gt;5&lt;/sub&gt;, and double the frequency of C&lt;sub&gt;3&lt;/sub&gt;. Semitones, the indivisible atoms of notes, were equally spaced with 12 to an octave. Multiplying rather than adding seemed to be the way to go, so I figured out that to get a semitone higher you multiplied by &lt;sup&gt;12&lt;/sup&gt;√2. I then wrote a cute little program to play Mary Had a Little Lamb, as if to prove that math really can't teach you about &lt;b&gt;music&lt;/b&gt;.&lt;/p&gt;

&lt;h3&gt;discord&lt;/h3&gt;
&lt;p&gt;I didn't really wonder why C made that G sound so good. That was an Art question, I didn't own a beret, and I was still cutting my hair at that point. But it was closely related to why all Cs sound the same.&lt;/p&gt;

&lt;p&gt;Notes forming a 'perfect' fifth have frequencies in the ratio 3/2. A fourth is the ratio 4/3 (so a fourth plus a fifth is an octave, 3/2 x 4/3 = 2). A third is 5/4 (major) or 6/5 (minor).
Problem is, these fractions aren't what you get when you glue a bunch of your &lt;sup&gt;12&lt;/sup&gt;√2 semitones together. 7 semitones is 2&lt;sup&gt;7/12&lt;/sup&gt; ≅ 1.4983 - 2% away from perfect harmony. The circle of fifths raises the pitch by (3/2)&lt;sup&gt;12&lt;/sup&gt; ≅ 129.74 times - 2% more than 7 octaves.&lt;/p&gt;

&lt;p&gt;So this music thing less of a &lt;a href="http://xkcd.com/179/"&gt;deep truth about the universe&lt;/a&gt; and more of a &lt;a href="http://xkcd.com/217/"&gt;weird and meaningless approximate coincidence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can tune your piano by&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Just_intonation"&gt;Setting the notes to nice fractions of C&lt;/a&gt; (but music in other keys will be out of tune)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Pythagorean_tuning"&gt;Finding notes with a circle of perfect fifths&lt;/a&gt;, but the fifth that joins the circle up will be too small, leaving (typically) G# and Eb badly out of tune&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Equal_temperament"&gt;Spreading the discrepancy equally across all notes&lt;/a&gt;, which is what we generally do now. It's regular and you can modulate betwteen keys freely.&lt;/li&gt;&lt;/ul&gt;

&lt;h3&gt;the thing about coincidences&lt;/h3&gt;
&lt;p&gt;You can find more if you look hard enough. There's no way to find an equal division of the octave that will give you a perfect fifth - or any nice harmonic. n 'semitones' in an m-division scale is 2&lt;sup&gt;n/m&lt;/sup&gt; which &lt;a href="http://en.wikipedia.org/wiki/Irrational_number#The_square_root_of_2"&gt;is irrational&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The next equal division size after 12 that can measure a fifth pretty accurately is 29 (3.6% error). 41 does better than 12 (1.6% error) and 53 is very good indeed (0.03% error). Music has been composed in these. I'm curious though, whether our familiar time signatures of 2, 3, 4, and 6 notes work as well in other divisions, or whether dividing evenly into the scale is an important attribute.&lt;/p&gt;

&lt;p&gt;And of course you can divide intervals other than an octave to form a scale. In particular I'm curious about an octave + fifth such as C&lt;sub&gt;4&lt;/sub&gt; - G&lt;sub&gt;5&lt;/sub&gt; - a 3:1 frequency ratio.&lt;/p&gt;

&lt;p&gt;Time to write some code, I guess.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-9197256136364632347?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/9197256136364632347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=9197256136364632347' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/9197256136364632347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/9197256136364632347'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/sound-of-music.html' title='the sound of music'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2750375898526248686</id><published>2007-11-12T01:50:00.000+13:00</published><updated>2007-11-22T01:29:13.407+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='broken'/><category scheme='http://www.blogger.com/atom/ns#' term='life'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='comic'/><title type='text'>I'm alive</title><content type='html'>&lt;p&gt;Went down to Dunedin for a couple of weeks to find something to do for a couple of years. Now that's ROI.&lt;/p&gt;

&lt;p&gt;My Mac's at the shop with a fried graphics chip. If the fault's of a certain nature, they'll replace the board free (out of warranty). Otherwise it's written off, and I (have|get) to buy a new one. I'm really hoping something, but I'm not sure what. &lt;/p&gt;

&lt;p&gt;In related news, linux+ubuntu runs really nicely on my four-year-old laptop - the same one that took weeks of enthusiastic tinkering when it was new. I guess they mature with age, like a fine wine, and long walks along the beach.&lt;/p&gt;

&lt;p&gt;I have it on good authority that it's not the internet without multimedia and hyperlinks.&lt;/p&gt;

&lt;p&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/JdxkVQy7QLM&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/JdxkVQy7QLM&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=JdxkVQy7QLM"&gt;Pachelbel Rant&lt;/a&gt; - Rob Paravonian&lt;/p&gt;

&lt;p&gt;&lt;a href="http://asofterworld.com/"&gt;a softer world&lt;/a&gt; - surreal webcomics, via &lt;a href="http://timsuth.tumblr.com"&gt;Tim&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh yeah, and i++ == 21. I sound less wrinkly that way.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2750375898526248686?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2750375898526248686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2750375898526248686' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2750375898526248686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2750375898526248686'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/11/im-alive.html' title='I&apos;m alive'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-6103968830266820651</id><published>2007-09-26T18:30:00.000+12:00</published><updated>2007-09-26T19:41:16.879+12:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groan'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Not a tree</title><content type='html'>&lt;a href="http://bp3.blogger.com/_exDwNmaRSoc/Rvn9AEQo2KI/AAAAAAAAAAc/iqrjAd0aJYE/s1600-h/424716811_b00a41767c.jpg"&gt;&lt;img src="http://bp3.blogger.com/_exDwNmaRSoc/Rvn9AEQo2KI/AAAAAAAAAAc/iqrjAd0aJYE/s320/424716811_b00a41767c.jpg" border="0" id="BLOGGER_PHOTO_ID_5114397029441263778" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-6103968830266820651?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/6103968830266820651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=6103968830266820651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/6103968830266820651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/6103968830266820651'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/09/not-tree.html' title='Not a tree'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_exDwNmaRSoc/Rvn9AEQo2KI/AAAAAAAAAAc/iqrjAd0aJYE/s72-c/424716811_b00a41767c.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-5078133544075047307</id><published>2007-08-31T01:58:00.000+12:00</published><updated>2007-11-22T01:28:17.164+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='money'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>The money's in the marketing</title><content type='html'>&lt;p&gt;Often you'll see a book mentioned on a website with a link to buy it on Amazon.com. The website owner has an account with Amazon and gets a commission when someone uses the link to buy the book.&lt;/p&gt;

&lt;p&gt;A bit of perspective I found shocking - the website owner earns as much as the author of the book.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.crystalreportsbook.com/SelfPublishing_02.asp"&gt;Source&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-5078133544075047307?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/5078133544075047307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=5078133544075047307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/5078133544075047307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/5078133544075047307'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/08/moneys-in-marketing.html' title='The money&apos;s in the marketing'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2993169678268641358</id><published>2007-08-25T17:01:00.000+12:00</published><updated>2007-11-22T01:27:50.506+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computers'/><category scheme='http://www.blogger.com/atom/ns#' term='cs'/><title type='text'>Sufficiently advanced technology</title><content type='html'>&lt;p&gt;I can't decide if it's magic or a rigged demo, but certainly the coolest thing I've seen in a while - a way to resize images without cropping or distorting the important details, by changing the amount of background. He even explains how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://youtube.com/watch?v=c-SSu3tJ3ns"&gt;Content-Aware Image Sizing&lt;/a&gt; on YouTube, if you can't see it below.&lt;/p&gt;

&lt;p&gt;&lt;object width="425" height="350"&gt;&lt;param name="movie" value="http://www.youtube.com/v/c-SSu3tJ3ns"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/c-SSu3tJ3ns" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2993169678268641358?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2993169678268641358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2993169678268641358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2993169678268641358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2993169678268641358'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/08/sufficiently-advanced-technology.html' title='Sufficiently advanced technology'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-1513323581257487519</id><published>2007-08-16T20:39:00.000+12:00</published><updated>2007-11-22T01:26:49.377+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cs'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><category scheme='http://www.blogger.com/atom/ns#' term='poetry'/><title type='text'>They don't make nostalgia like they used to</title><content type='html'>&lt;p&gt;Was digging through an old server looking for something, and ran into a weird array of stuff&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Silly flash games&lt;/li&gt;
&lt;li&gt;Silly &lt;a href="http://hostfile.org/goldrush.zip"&gt;first year compsci assignments&lt;/a&gt;, from when I believed in doing assignments properly (and they were games)&lt;/li&gt;
&lt;li&gt;Silly second year compsci assignments from when I believed in doing assignments at all&lt;/lI&gt;
&lt;li&gt;&lt;a href="http://hostfile.org/RobotFindsKitten.exe"&gt;My very own&lt;/a&gt; &lt;a href="http://robotfindskitten.org/"&gt;Robot Finds Kitten&lt;/a&gt; in an exciting new language called C#&lt;/li&gt;
&lt;li&gt;A video of a perfect zero in &lt;a href="http://skinflake.com/games/truckdismount"&gt;Truck Dismount&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the weirdest thing, that I don't remember a word of, but must have written because google's never heard of it:&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;I am the very model of a mildly tricky integral
So easy to approximate on any given interval
But general solutions need a stroke of ingenuity
To find a strategem which rectifies discontinuity.
You'll try the things you learned in class but never gain much traction
With your clever substitutions and techniques of partial fractions
In short, your simple methods fail against one so formidable,
I am the very model of a fairly tricky integral.

Combining basic processes in any way conceivable
Still fails to make the answer appear any more achievable
Rewriting points in polar form pre-partial integration
Does not subtract, but adds, to the solution's complication.
There seems to be no way to find a formula constructively
And thus no proposition one can try to prove deductively
The Riemann sum's don't simplify when working from first principles
I am the very model of a rather tricky integral.

I stood almost unchallenged for the best part of a century
And people wondered if my answer's even elementary
Professors thought they'd solved me and they harboured animosity
When refutations flooded in with frightening ferocity.
And then one day a student who, for rhyme's sake, will be Asian
Was trying hard to visualise the shape of my equation
The integrand examined, the identity, though difficult,
Did give the model answer for the very tricky integral.

(So while it seems that "reader's exercises" should be trivial,
Sometimes it's just a reason not to solve some tricky integral)&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-1513323581257487519?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/1513323581257487519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=1513323581257487519' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1513323581257487519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/1513323581257487519'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/08/they-dont-make-nostalgia-like-they-used.html' title='They don&apos;t make nostalgia like they used to'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-3684440637803757734</id><published>2007-08-06T22:29:00.000+12:00</published><updated>2007-11-22T01:26:07.776+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apple oops'/><title type='text'>iPhone has performed an illegal operation and will be shut down</title><content type='html'>&lt;p&gt;&lt;img src="http://bp2.blogger.com/_exDwNmaRSoc/Rrb4tV6t9qI/AAAAAAAAAAU/RWaPfgF1qdg/s320/Windows-iPhone.jpg" border="0" alt="Oops!" id="BLOGGER_PHOTO_ID_5095533486277523106" /&gt;&lt;/p&gt;

Oops.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-3684440637803757734?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/3684440637803757734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=3684440637803757734' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3684440637803757734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/3684440637803757734'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/08/iphone-has-performed-illegal-operation.html' title='iPhone has performed an illegal operation and will be shut down'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_exDwNmaRSoc/Rrb4tV6t9qI/AAAAAAAAAAU/RWaPfgF1qdg/s72-c/Windows-iPhone.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-2549149214746402009</id><published>2007-08-03T00:33:00.000+12:00</published><updated>2007-11-22T01:25:28.481+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comic'/><title type='text'>xkcd</title><content type='html'>&lt;p&gt;You know when you see an &lt;a href="http://dictionary.reference.com/browse/repast"&gt;unfamiliar word&lt;/a&gt; in an essay or such, and you look it up, and all of a sudden it's everywhere? It's clearly not a new word and maybe everyone was using it before without you noticing, but it still seems to have turned up overnight. It's &lt;a href="http://steve-yegge.blogspot.com/2006/12/i-take-it-all-back-send-me-your-money.html"&gt;essay molasses&lt;/a&gt; I guess. &lt;br /&gt;
Anyway, the word of the week is &lt;a href="http://xkcd.com/"&gt;xkcd&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Wikipedian Protester&lt;/h4&gt;
&lt;p&gt;&lt;img alt="Cartoon: Wikipedian Protester" src="http://imgs.xkcd.com/comics/wikipedian_protester.png" /&gt;&lt;/p&gt;

&lt;p&gt;Maybe I read too much wikipedia.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;edit&lt;/b&gt; &lt;a href="http://xkcd.com/262/"&gt;hahahhahahahahahahhahaha&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-2549149214746402009?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/2549149214746402009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=2549149214746402009' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2549149214746402009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/2549149214746402009'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/08/xkcd.html' title='xkcd'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-8400451208218518503</id><published>2007-08-01T00:15:00.000+12:00</published><updated>2007-11-22T01:23:23.755+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groan'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Telephone trouble</title><content type='html'>&lt;p&gt;It seems that every Monday morning when I get into the office &amp;mdash; not &lt;b&gt;on time&lt;/b&gt; as such, but 'morning' is usually accurate &amp;mdash; there's already an email saying they're having some problem or other with the phone system. A weird but harmless error message, calls randomly connecting to the wrong phone, bizarre error messages, whatever.&lt;/p&gt;&lt;p&gt;Backhanded compliment though, I bet even Simon doesn't have a weekly inaccessible telephone number!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-8400451208218518503?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/8400451208218518503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=8400451208218518503' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/8400451208218518503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/8400451208218518503'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/07/telephone-trouble.html' title='Telephone trouble'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6809957905702392707.post-6082283944865887377</id><published>2007-08-01T00:00:00.000+12:00</published><updated>2007-11-22T01:24:50.601+13:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='broken'/><category scheme='http://www.blogger.com/atom/ns#' term='facebook'/><title type='text'>Facebook</title><content type='html'>&lt;p&gt;Yeah, you got me. I signed up for the thing. I posted an impassioned disclaimer-rant about how Facebook struck me as potentially flaky and devoid of content. I came back ten minutes later and edited it to complain about the markup mangling, and went to bed. &lt;/p&gt;
&lt;p&gt;Today it's gone. &lt;/p&gt;
&lt;p&gt;I can't write coherently at the best of times, and I'm out of practice, so it's no great loss to the world. Flaky isn't the word though. I tried to post a note mentioning it (not a fast learner, you see) and among other error messages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;You have not written any notes.&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Displaying the only note by you.&lt;/i&gt; (followed by a blank space)&lt;/li&gt;
&lt;li&gt;Write a New Note &amp;#x2192; &lt;i&gt;Your friends have not written any notes yet.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accompanied by a handy tip: &lt;i&gt;You can write your own or find more friends&lt;/i&gt;. Ouch. &lt;/p&gt;

&lt;p&gt;I haven't played with the other standard apps yet, are they any better?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;edit&lt;/b&gt; And it's back again. I think I've learned my lesson though.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6809957905702392707-6082283944865887377?l=blog.abstractable.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.abstractable.net/feeds/6082283944865887377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6809957905702392707&amp;postID=6082283944865887377' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/6082283944865887377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6809957905702392707/posts/default/6082283944865887377'/><link rel='alternate' type='text/html' href='http://blog.abstractable.net/2007/07/facebook.html' title='Facebook'/><author><name>Sam McCall</name><uri>http://www.blogger.com/profile/08193244312398482089</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://bp3.blogger.com/_exDwNmaRSoc/RzrnTwmcD1I/AAAAAAAAAAk/PB3IfU8MIHE/s320/sam_sm.jpg'/></author><thr:total>0</thr:total></entry></feed>
