I'm Paul Bissex, and e-scribe.com is my consulting business. I build web applications using open source software, especially Django. In the '90s I did graphic design for newspapers and magazines. Then I wrote technology commentary and reviews for Wired, Salon.com, Chicago Tribune, and lots of little places you've never heard of. Feel free to email me.
I'm co-author of "Python Web Development with Django", an excellent guide to my favorite web framework. Published by Addison-Wesley, it is available from Amazon and your favorite technical bookstore as well.
Built using Django, served by Apache and mod_wsgi. The database is SQLite. The operating system is FreeBSD, on a VPS hosted at Johncompanies.com. Comment-spam protection by Akismet. Vintage topo imagery from the Maptech archive. The markup engine is Markdown.
Akismet, del.icio.us, Django, dpaste.com, Emacs, FreeBSD, Freenode, jQuery, LaunchBar, MacPorts, Markdown, Mercurial, OS X, Postfix, Python, SQLite, Subversion, TextMate, Trac, Ubuntu Linux, wmii
At least 70644 pieces of comment spam killed since January 2008, mostly via Akismet.
lambdas in a single line and weighs in at 105 bytes. I thought this might be the best possible in Python 2.4 and earlier, but in fact a simpler version can be constructed using the old short-circuit logic trick, and at 94 bytes it's even smaller than my original. Here it is: q=lambda s:len(s)and q([x for x in s[1:]if x<s[0]])+[s[0]]+q([x for x in s[1:]if x>=s[0]])or sEnticed by the lovely Haskell quicksort example, and sullied by the code-crunching ways of Codegolf, I decided to see how small a Python quicksort function I could write. I stopped at 99 bytes.
>>> q=lambda s:s if len(s)<2 else q([x for x in s[1:]if x<s[0]])+[s[0]]+q([x for x in s[1:]if x>=s[0]])
>>> print q([9,7,5,3,1,8,6,4,2])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
(If that's hard to read, try the colorized version.)
This requires Python 2.5 because of its use of the new ternary x-if-y-else-z syntax. Please, no style comments! Unreasonable compression is the whole point. I have to say, though, that in terms of readability Python holds up better than most languages under this kind of treatment. Not so much in this example, though...
Here is a slightly shorter program at 86 bytes:
q=lambda s:s and q([x for x in s[1:]if x=s[0]])
And even shorter, at 82 bytes:
e='q([x for x in s[1:]if x';q=lambda s:s and eval(e+'=s[0]])'%e)
Let's try that again:
q=lambda s:s and q([x for x in s[1:]if x<s[0]])+[s[0]]+q([x for x in s[1:]if x>=s[0]])
e='q([x for x in s[1:]if x';q=lambda s:s and eval(e+'<s[0]])+[s[0]]+%s>=s[0]])'%e)
Slightly rearranging gets a 79 byte version:
e='q([x for x in s[1:]if s[0]';q=lambda s:s and eval(e+'>x])+[s[0]]+%s<=x])'%e)
Is this really quicksort in terms of how many opertations this consumes? It seems to me that this version goes through each intermediate list twice, where as the canonical version of quicksort should do it only once. Of course the canonical version also does two operations inside the iteration.
I'd have to go through this with paper and pen, but will Santa approve me writing down pseudocode at the Xmas dinner?
It'd be enlightening to do performance comparisons between this code and the "old way" of doing quicksort, though.
I believe the biggest factor that makes this not-a-real-quicksort is that it doesn't sort the items in place. I blame the Haskell guys for starting it!
A version which more closely resembles the original:
q=lambda s:[] if s==[] else q([x for x in s[1:]if x=s[0]])
This pretty closely resembles the canonical Haskell quicksort:
sort [] = []
sort (x:xs) = sort (filter (<x) xs) ++ [x] ++ sort (filter (>=x) xs)
And this reduces to a paltry 45 bytes:
q[]=[];q(h:t)=q[x|x<-t,x<h]++h:q[x|x<-t,h<=x]
An excellent example of why I think it would be interesting to add Haskell to [Codegolf][]!
(I patched up your comment, BTW. Anti-spam measures make posting code a bit harder than it should be.)
[codegolf]: http://codegolf.com/
Prompted by Antti Rasinen's comment, I ran some comparisons. The algorithm in the original post runs about 0.5% faster than a "standard" Python quicksort; the others were buggy and I couldn't figure out how to get them to work.
Thanks for reading! Please note: Your comment will not appear until approved, which may take a few hours or more. Spammers will be torpedoed.
A different kind of URL shortener
4 comments
The syncbox
2 comments
Branching and merging in real life
8 comments
Summer Spam
1 comment
SPF-enabled spam domains
1 comment
Brian Johnson
A different kind of URL shortener
Yesterday
Adrian Holovaty
A different kind of URL shortener
3 days ago
Ian Bicking
A different kind of URL shortener
4 days ago
aman
Sort tables with sorttable.js
10 days ago
spiele
Let's play a game: BASIC vs. Ruby vs. Python vs. PHP
42 days ago
Copyright 2010
by Paul Bissex
and E-Scribe New Media
Isn't "def q(s):" shorter than "q=lambda a:" ?