Ninja Code
As this is only my second post—my first merely being a plug for a Damian Conway talk at my local Perl Mongers meeting—I thought I’d keep it short and silly.
At OSCON 2008, Amazon had a prominent booth advertising heavily that they were hiring. They didn’t want to hire just anyone. No, the question posed on the large sheet of poster board was, “Are you a ninja coder?” This was combined with a raffle, which as anyone who has ever been to a conference knows, is the most common tool used to get people to hand over their contact information. To enter, one had simply to look over some Perl code written out on that same poster board and tell them what it did. It looked a little something like this:
my $code = qq{
print 1+1 . "\n";
$code =~ m/(\d+)\+(\d+)/;
$new = $1 + $2;
$code =~ s/\d+\+(\d+)/$2+$new/;
};
for ( 1 .. 10 ) {
eval($code);
}
Do you see the bug? It’s actually besides the point, but it’s there.
Yes, it should use q{}
, or the variables will interpolate on the initial assignment to $code
. To the credit of those staffing the booth, when I pointed this out they responded that the original version used single quotes, but people told them it was too hard to read.
I wasn’t content with just figuring out what the code did and fixing a small bug. I think the code itself can be improved upon. So I hacked something up between sessions:
eval($code = q{
print 1+1 . "\n";
$code =~ s/(\d+)(\+)(\d+)/"$3$2" . ($1 + $3)/e;
eval $code;
});
Much better. Not only is it more concise, I was able to remove that pesky loop, so I wouldn’t be bothered by any silly upper bounds. Except for, you know, overflows and stuff. What’s more, it’s given me something to scare interview candidates with.
Yeah, that is a pretty interesting way to write that :-)
You should be writing Modern Perl!
It breaks down on the 89th iteration, btw, which I checked and found is when the result exceeds 61 bits. Perl also starts outputting scientific notation at that point, and three iterations later the output becomes entirely nonsensical.
Sticking a “
use bigint;
” in there fixes the output format but the results are still worthless. Apparently the parser hits its precision limit for literals at that point.Technically two bugs: the s/// replacement also has one. (Or perhaps that was a typo in transferring?)
You're right, and it's glaringly obvious now that I see it. I originally wrote something about this while at OSCON back in 2008, so I no longer remember if it was their bug or my transcription error. Though it might explain why my original writeup stated, "Do you see the first bug?" I didn't have anything about a second, so I changed the phrasing.
Nice catch, thanks.
"Write a Perl script to print the first 10 numbers of the Fibonacci sequence" is one of our standard interview questions - not had anybody write it like this yet ;-)