I had started down a similar path inspired by the same node, but focusing on hex  and stopping abruptly when I got busy on more pressing ($workrelated) issues :). I built the times and addition tables, and had started on my addition subroutine... but this is as far as I got. Posted for entertainment value only. :)
package HexMath;
# add or multiply hexadecimal
my (%times, %sums);
BEGIN { # create tables
for my $x ( 0 .. 15 ) {
my $hx = sprintf '%x', $x;
for my $y ( 0 .. 15 ) {
my $hy = sprintf '%x', $y;
next if exists $times{$hx}{$hy};
$times{$hx}{$hy} = $times{$hy}{$hx} = sprintf '%x', $x*$y;
$sums{$hx}{$hy} = $sums{$hy}{$hx} = sprintf '%x', $x+$y;
}
}
printf "\n%4s: ", 'x ';
printf "%4x ", $_ for 0..15;
for my $x ( 0 .. 15 ) {
my $hx = sprintf '%x', $x;
printf "\n%4.4s: ", $hx;
for my $y ( 0 .. 15 ) {
my $hy = sprintf '%x', $y;
printf '%4.4s ', $times{$hx}{$hy};
}
}
print "\n";
printf "\n%4s: ", '+ ';
printf "%4x ", $_ for 0..15;
for my $x ( 0 .. 15 ) {
my $hx = sprintf '%x', $x;
printf "\n%4.4s: ", $hx;
for my $y ( 0 .. 15 ) {
my $hy = sprintf '%x', $y;
printf '%4.4s ', $sums{$hx}{$hy};
}
}
print "\n";
}
sub add {
my $answer = shift;
while( defined(my $addend = shift)) {
substr($answer,0,0,'0'x(length($addend)length($answer))) if l
+ength($answer) < length($addend);
substr($addend,0,0,'0'x(length($answer)length($addend))) if l
+ength($addend) < length($answer);
print "$answer + $addend = ";
my $c = 0;
for my $hexit ( 1 .. length($addend) ) {
my $x = lc substr($answer, $hexit, 1);
my $y = lc substr($addend, $hexit, 1);
my $s = $sums{$x}{$y};
#my $u =
printf "\n\t#%d: %s + %s = %s\n", $hexit, $x, $y, $s;
}
print "$answer\n"
}
}
package main;
HexMath::add('a','b','cqcq','d');
