User loginNavigationThe postings on this site are my own and don't necessarily represent IBM's positions, strategies, or opinions. |
dvhart's blogScanning Package that Doesn't SuckYou've received that email, "Please print, sign, scan, and return." Possibly it said FAX - but like me, you just can't wrap you're head around using a FAX in 2010. So you fire up gimp (or xsane), scan a page, crop it, save it; repeat for N pages; then spend 10 minutes reading the absurdly obfuscated ImageMagick man pages to finally stitch the images together into a PDF, and return to sender. You do this once, and the memory of it provides a very significant mental barrier to ever repeating the process. I had to do this again today for a pair of documents. The Simple Scan tool caught my eye and I gave it a try. It's pure genius, in an "OMFG why did it take 10 years for this to appear?" kind of way. Simple Scan handles the intermediate files behind the scenes, crops all the pages to the same size, displays a thumbnail of each page you scan, and finally saves the document as a PDF. Like, wow. Thanks Simple Scan!
Maximizer: The Replacement Laptop DilemmaI just got back from a trip to Best Buy to fondle a wide selection of laptops. Considering they don't carry the "business" line from HP or others, there is a giant gap between the consumer laptops and the Mac Book Pro. It would be like going to a car dealer that sold Kias and BMWs (no offense to all the Kia drivers who wait with baited breath for my next awe-inspiring blog post). I spent about an hour typing on some 20 keyboards and testing the flex of the chassis and keyboard. Most were Chiclet style keyboards, which turns out to be a sub-optimal design (in my opinion) if you use more than two fingers to type.
It's now abundantly clear to me, there are only two choices when it comes to quality professional grade notebooks: Lenovo ThinkPad and Mac Book Pro. My second discovery is that my belief that Macs were overpriced is completely false. You can't compare a Mac to a Dell or an Acer (not even an HP consumer grade machine), you have to compare it to the top of the line Lenovo ThinkPads (T510, x201s, x301, etc.) and then, feature for feature, the Mac is competitively priced. Damn.
Red Black Trees
An rbtree achieves O(log n) time complexity for search, insert, and remove. The key properties of an rbtree are as follows:
I finally manned-up and decided to write a sample red black tree in python. Despite having covered binary trees ad nauseam in college, I was surprised how challenging it was to write a completely functional red black tree. After a few nights of "free time" dedicated to the project, I finally have something to show for it. $ ./rbtree.py ***** Populating Red Black Tree with 1000 Nodes ***** ***** Test Insert Complexity O(log N) ***** PASS ***** Test In-Order Traversal ***** PASS ***** Test Search Complexity O(log N)***** PASS ***** Test Remove Functionality ***** PASS The source comes with a built-in self test that inserts the values 1-1000 in random order, locates them all, then removes them in random order. It verifies the 5 properties of the rbtree at each step, and prints the results. While I am glad to have done it, I am truly embarrassed at how long it took me to complete. On the bright side, the principles I had to dust off to get this done are now painfully fresh in my head. If you'd like to see the source, it's available here: rbtree.py Lastly, there is a clever interactive demo here (requires java): Next up... python metaclasses, and why Guido is an evil bastard.
Not less than, not greater than, but not equal either!I've been twice bitten by this subtlety of the python __cmp__() method, I thought I'd try to save you the same pain (and perhaps by writing it down I won't repeat it... again). When dealing with objects, it's often useful to be able to compare these objects:
if mySwartz > yourSwartz:
print "Suck it."
An obvious (and wrong) __cmp__() method would be:
def __cmp__(mine, yours):
if mine.val < yours.val:
return -1
if mine.val > yours.val:
return 1
return 0
Looks good right? Well, what if some yahoo tries to compare two totally disimilar things, i.e:
if mySwartz > yourForce:
print "Neener Neener."
Such a comparison clearly makes no sense, so let's update __cmp__() to check for similar data types:
def __cmp__(mine, yours):
if not isinstance(yours, Swartz):
return -1
if mine.val < yours.val:
return -1
if mine.val > yours.val:
return 1
return 0
Good right? WRONG. Consider the following ridiculous scenario: mySwartz.val == yourSwartz.val While I'm sure no such thing could happen, let's imagine for the sake of argument that two objects might be compared on an internal value that just might not be unique across all instances of the object. What would happen if you had to retrieve your object from a container?
storage = []
storage.append(yourSwartz)
storage.append(mySwartz)
# time passes
for sw in storage:
if sw == mySwartz:
print "I found my Swartz!"
print "...wait... this is your Swartz... gah!"
Yeah yeah, you could rewrite this to yada yada, that's not the point. The point is while the values of the objects are the same, they are not the same objects and python uses the __cmp__() method for both less than, greater than, equality, AND identify comparison if you're used to thinking of your objects as pointers! If you're faced with a situation where you want to be able to easily sort objects, but still need to be able to identify them uniquely when they share an internal value, augment your __cmp__() routine to check for id as well:
def __cmp__(mine, yours):
if not isinstance(yours, Swartz):
return -1
if mine.val < yours.val:
return -1
if mine.val > yours.val:
return 1
if id(mine) < id(yours):
return -1
if id(mine) > id(yours):
return 1
return 0
If you're a python guru and think I'm missing something, please share, otherwise:
if mySwartz > yourSwartz:
print "I see my Swartz is bigger than yours..."
From the Why-didn't-I-do-this-before department (vim+cscope)I finally got tired of lack specifiers in "git grep" and the cscope ncurses interface. I spent a few minutes and setup the vim cscope plugin using this mighty fine tutorial: http://cscope.sourceforge.net/cscope_vim_tutorial.html The one gotcha I ran into was having to disable my vim setting that automatically changed the working directory to that of the open file - it broke the cscope plugin relative filenames. " automatically switch the cwd to that of the file in the buffer " This breaks cscope plugin " autocmd BufEnter * :cd %:p:h Very, VERY VEERRRYYY nice. Now if only I could get a full call graph out of it...
Backup FS: Getting StartedI use rdiff-backup to keep a few months worth of daily backups for my home systems (and those of my parents for that matter). The ability to recover any version of a file is great - although the process still requires a geek (me). $ rdiff-backup --restore-as-of "7D" user@backupserver::/path/to/backup/file Wouldn't it be great if you could just mount the backup repository and browse by path or date and then just copy the desired version? Enter BackupFS, a fuse filesystem implemented with rdiff-backup. I've only just started digging into this, and rdiff-backup's python packages were not intended to be used as libraries (not with all the code buried in rdiff_backup.Main and all the global module variables floating around. Still, I was able to get a server test and a listing of the repositories root increments by using the python modules (and not just making multiple subprocess() calls). I have a glorified version of the example hello world fuse filesystem able to mount and list a few meta-directories: dvhart@vin:backupfs.git$ ./backupfs.py mnt && (tree mnt; fusermount -u mnt) Testing server started by: ssh -C katara rdiff-backup --server Server OK mnt |-- By Date | `-- increments.2010-01-07T22:11:42-08:00.dir |-- By Path `-- hello 3 directories, 1 file Fatal Error: Lost connection to the remote system I still have some basic research to do in order to understand how to operate within the rdiff-backup packages (API isn't quite the right term ;-). After that, it'll be on to a more formal design and then some nicer code.
It just worked?I had Dad ship his old laptop for an upgrade. After installing Ubuntu Lucid (from a USB key) and upgrading the RAM, I was _really_ impressed that Empathy video chat over Google Talk "just worked". I went and picked up a Logitech C120 web-cam for him for $20, took it home, plugged it in the USB slot and guess what - it just worked! We've come a long way in 10 years Linux! Honestly it felt weird... I kept thinking... isn't there a driver I should have to download, build, fix, patch, build, etc... It's like... having a mac or something. The only thing that would have made it better would be if the box had a penguin logo on the back.
Commuting by Bike: Day 2Made my second commute in on my Jamis Commuter 3 today, this time in the rain! Some lessons learned:
New used car^W vanIt's finally done. We found a 2007 Honda Odyssey in a color we like with the features we wanted (EX-L, leather, DVD), with the miles mlhart was happy with (< 36k). The exterior had some scratches where the bumpers bumped (they are awfully low) and the carpet has the tel-tale signs of children with muddy feet and cherry Popsicles having enjoyed a ride or a thousand. Being willing to accept these blemishes saved us $11k over a new one. We plan to drive it for a month or so and then take it to have some body work done and then on over for a thorough detailing. The sellers were reasonable and pretty straight with us - which is a lot more than I can say of my previous experiences. Buying used from a private party was the way to go for us.
Commuting by Bike: Day 1I picked up my shiny new Jamis Commuter 3 on Thursday. I opted for the 21" over the 19" even though it doesn't offer as much stand-over clearance as I'd like. I had to raise the seat above the height of the handlebars on the 19" which wasn't the ride I was looking for. I also found my toe would clip the front fender on tight turns which bothered me (perhaps more than it should have). All in all, the 21" just felt more comfortable. So after getting it and the various safety and security accessories home, I took a few getting-to-know-you rides around the neighborhood and today (just 30 minutes ago) made my first commute by bike into work. I picked a route that avoided the busier roads without bike lanes as well as dodging around some of the steeper inclines. It took me through our park on a path around the lake before dumping me out on Walker Rd for the last stretch. Nike threw a nice hill at me toward the end, but IBM let me coast the last quarter mile on a generous incline to the parking lot. I am very glad for the 8-speed Shimano Nexus hub, a single-speed would likely have been an excuse not to ride. 15 minutes elapsed time door to door, it might take me a little longer to work the burn out of my legs and to get rid of "that funny feeling in my tummy". All in all, I think it's a great start. Thanks to everyone that offered advice and encouraged me to start riding in!
|
Lumberjocks ProjectsRead |