Bad Perl: Russian Peasant multiplication algorithm

I found this programming contest interesting: here’s what I’ve got.

perl -e "($a,$b)=@ARGV;map{$c+=$_*$b}grep{$a&$_}map{1<<$_}(0..log($a)/log 2);print$c" 7 19

I’m calling this a one-liner because the part between the quotes is less than 80 characters (75, to be exact.)  The full command line goes over 😦

Requires the inputs to be positive whole numbers.

Perfect example of Bad Perl.  Exercise: rewrite in Good Perl.

EDIT: got the whole thing down to 80 characters (with single-digit multiplicands.)

perl -e "($a,$b)=@ARGV;map{$c+=$b<<$_ if$a>>$_&1}(0..log($a)/log 2);print$c" 8 7

Good Perl, Bad Perl

One of my favorite languages is Perl.  Perl has an ambivalent reputation; some people take to it, some accuse it of being a syntax-complete language.  (There’s some truth to this.)

My view is that Perl gives you a very direct link into the mind of the programmer – much more so than other languages.  Perl is designed very much like a spoken language, perhaps because Larry Wall‘s background is linguistics.

There was a little girl
Who had a little curl
Right in the middle of her forehead.
And when she was good,
She was very, very, good;
But when she was bad
She was horrid.
   — Henry Wadsworth Longfellow

(In an English accent, “forehead” and “horrid” actually rhyme.)

Two examples of my own Perl to illustrate my point.  This is in my email signature:

perl -e "print join er,reverse',','l hack',' P','Just anoth'"

And this little seasonal gem:

use strict;
use warnings;

sub receive($);

my @ordinals = qw(
	first second third fourth fifth sixth
	seventh eighth ninth tenth eleventh twelfth

my @gifts = reverse split /n/, <<END_OF_LIST;
	Twelve drummers drumming;
	Eleven pipers piping;
	Ten lords a-leaping;
	Nine ladies dancing;
	Eight maids a-milking;
	Seven swans a-swimming;
	Six geese a-laying;
	Five golden ringeds;
	Four colly birds;
	Three French hens;
	Two turtle doves;
	A partridge in a pear tree.

for (my $day = 1; $day <= 12; $day++) {

sub receive($) {
	my $day = shift;

	print("On the ", $ordinals[$day], " day of Christmas, my true love sent to me:n");

	for (my $i = $day; $i > 0; $i--) {
		my $gift = $gifts[$i - 1];

		if ($i == 1 && $day != 1) {
			$gift =~ s/^(s*)A/$1And a/;

		print $gift, "n";

	if ($day != 12) {
		print "n";

The latter kind of Perl I like to call “good Perl”.  It’s easy to read, I think.  There are a couple of idioms that take getting used to, just like with any new language, but well-written Perl is (I think) easier to read than any other language.

But flexibility has its dark sides as well.  Black Perl is the canonical example, but there are others such as Perl golf.  This kind of thing (the first sample above is an example) is responsible for at least part of Perl’s reputation for opacity; its compatibility with shell scripting, and most particularly its embedded regular expression support, is responsible for much of the rest.

Exercise: duplicate the output of the second sample above using as short a Perl program as possible.