Skip eval and hard-code tr///:
sub usingtr_d {
my $a = $aa;
my $b = $bb;
# Delete ACGT first, assuming these are the
# most common characters.
abs($a =~ y/A//d - $b =~ y/A//d) +
abs($a =~ y/C//d - $b =~ y/C//d) +
abs($a =~ y/G//d - $b =~ y/G//d) +
abs($a =~ y/T//d - $b =~ y/T//d) +
abs($a =~ y/B// - $b =~ y/B//) +
abs($a =~ y/D// - $b =~ y/D//) +
abs($a =~ y/E// - $b =~ y/E//) +
abs($a =~ y/F// - $b =~ y/F//) +
abs($a =~ y/H// - $b =~ y/H//) +
abs($a =~ y/I// - $b =~ y/I//) +
abs($a =~ y/J// - $b =~ y/J//) +
abs($a =~ y/K// - $b =~ y/K//) +
abs($a =~ y/L// - $b =~ y/L//) +
abs($a =~ y/M// - $b =~ y/M//) +
abs($a =~ y/N// - $b =~ y/N//) +
abs($a =~ y/O// - $b =~ y/O//) +
abs($a =~ y/P// - $b =~ y/P//) +
abs($a =~ y/Q// - $b =~ y/Q//) +
abs($a =~ y/R// - $b =~ y/R//) +
abs($a =~ y/S// - $b =~ y/S//) +
abs($a =~ y/U// - $b =~ y/U//) +
abs($a =~ y/V// - $b =~ y/V//) +
abs($a =~ y/W// - $b =~ y/W//) +
abs($a =~ y/X// - $b =~ y/X//) +
abs($a =~ y/Y// - $b =~ y/Y//) +
abs($a =~ y/Z// - $b =~ y/Z//);
}
Benchmarks, including roboticus' robo_1, trizen's
match, and choroba's tr_1e:
Rate tr grep tr_1e sg match robo_1 tr_d
tr 843/s -- -18% -56% -75% -80% -92% -99%
grep 1022/s 21% -- -47% -70% -76% -90% -99%
tr_1e 1915/s 127% 87% -- -44% -55% -81% -98%
sg 3419/s 306% 235% 79% -- -20% -66% -97%
match 4291/s 409% 320% 124% 25% -- -57% -96%
robo_1 9984/s 1085% 877% 421% 192% 133% -- -90%
tr_d 100985/s 11881% 9784% 5175% 2853% 2254% 911% --
Tested against these strings, which are ~80% ACGT:
my @alpha = ('A'..'Z', qw[ A C G T ] x 20);
my $aa = join '', map $alpha[rand @alpha], 1..100;
my $bb = join '', map $alpha[rand @alpha], 1..100;