Tuesday, August 4, 2009

Importance of variable naming and whitespace

Last week, I decided just for the fun of it to take a crack at this crazy programming contest http://thedailywtf.com/Articles/Programming-Praxis-Josephus-Circle.aspx I didn't want to spend much time on it, so instead of trying to do it in some esoteric programming language, I turned to the language I am most familiar with: Perl. I created something that works and then I made it ugly. Really ugly.

For comparison, I'll show the ugly version first - originally crammed onto one VERY long line. I had to fix the formatting a bit so it would show up here.

($c,$s)=@ARGV;@s=(1)x$c;$ls=$c;my($i,$sk)=(0,0);while($ls>1){$sk=$s[$i]?($sk+1):$sk;if($s[$i]&&($sk eq $s)){$s[$i]=0;$ls--;$sk=0;} $i=($i eq ($c-1))?0:($i+1);}$i=0;foreach my$s(@s){$i++;if($s){last;}}print"Safe $i\n";

And here is the original version before I uglified it. I know it doesn't look like it, but these two pieces of code do the exact same things.

#!/usr/bin/perl -w
use strict;

my ($count, $skip) = @ARGV;
my @soldiers = (1) x $count;
my $live_soldiers = $count;
my $i = 0;
my $sk = 0; #skip counter
while ($live_soldiers > 1) {
$sk = $soldiers[$i] ? ($sk + 1) : $sk;
if ($soldiers[$i] && ($sk eq $skip)) {
$soldiers[$i] = 0;
$sk = 0;
$i = ($i eq ($count - 1)) ? 0 : ($i + 1);
$i = 0;
foreach my $s (@soldiers) { $i++; if ($s) { last; } }
print "Safe spot is $i\n";

As you can see, in the second version, you can *almost* tell what it does just by reading the code. Adding a couple comments and named command line arguments and it wouldn't be that bad. It would also need error checking.

The only real difference between the two is I removed the whitespace I could and made all the variables one or two characters.

As you can see, it is possible to write readable Perl. It is also very easy to write completely unreadable Perl, but that can be said of any language I've seen.