If you really want to do it in one, then the following is a way:
my @array = (undef, map([undef, map($_-64, unpack('C3', $_))],
unpack('(A3)*', $string))
+) ;
The thing to watch out for with nested
maps is the reuse of
$_, but in this case it's fine.
Just for the hell of it, I threw a little benchmarking at it:
Rate W1SDM GrandFather GMCH
W1SDM 7.59/s -- -30% -48%
GrandFather 10.9/s 43% -- -25%
GMCH 14.6/s 93% 34% --
which tells you that this can go almost twice as fast if you throw certain amount of magic at it. The question is: does this affect the price of cocoa ? And the other question is: if so, was the effect worth the effort ?
Update: ah... same trick as AnomalousMonk above.
use strict ;
use warnings ;
my $string = "BEHACJBDLCENADFEGOFHQAGIHJRBIKJLSCKMLNTDMOFNPOQTGPRIQSKR
+TMPS";
my @results = () ;
collect('W1SDM', W1SDM($string)) ;
collect('GrandFather', GrandFather($string)) ;
collect('GMCH', GMCH($string)) ;
printf("%12s %12s %12s\n", @$_) foreach @results ;
use Benchmark qw(cmpthese) ;
cmpthese(100, { W1SDM => sub { W1SDM($string) for (1..100
+0) },
GrandFather => sub { GrandFather($string) for (1..100
+0) },
GMCH => sub { GMCH($string) for (1..100
+0) },
}
) ;
sub collect {
my ($t, $r) = @_ ;
push @{$results[0]}, $t ;
push @{$results[$_]}, sprintf "%02d %02d %02d", @{$r->[$_]}[1..3] fo
+r (1..$#$r);
} ;
sub W1SDM {
my ($string) = @_ ;
my @array = split //, $string;
my @result = () ;
for my $i (1..20) {
for my $j (1..3) {
$result[$i][$j] = ord(shift(@array)) - 64;
}
}
return \@result ;
} ;
sub GrandFather {
my ($string) = @_ ;
my @array = (undef);
push @array, [0, map {ord ($_) - 64} split '', substr $string, 0, 3,
+ '' ]
while length $string;
return \@array ;
} ;
sub GMCH {
my ($string) = @_ ;
my @array = (undef, map([undef, map($_-64, unpack('C3', $_))],
unpack('(A3)*', $st
+ring))) ;
return \@array ;
} ;