sub checkUPCGrandFather2 {
my $str = shift;
return "should be 12 digits in length" if length ($str) != 12;
my $t = 0;
my $sum = 0;
# loop through to sum even and adjusted odd chars
for (0..10) {
my $chr = substr $str, $_, 1;
$sum += ($t ^= 1) ? $chr * 3 : $chr;
}
# calculate correct check digit
my $check = (10 - $sum % 10) % 10;
# return error message if wrong check digit was initially given
return ($check != substr $str, 11) ? "invalid checkdigit...should be $check" : 'Ok';
}
####
checkUPCGrandFather1: invalid checkdigit...should be 6
checkUPCGrandFather2: invalid checkdigit...should be 6
checkUPCroboticus: invalid checkdigit...should be 6
checkUPCEvanK: invalid checkdigit...should be 6
Rate GrandFather1 EvanK roboticus GrandFather2
GrandFather1 21630/s -- -11% -19% -72%
EvanK 24183/s 12% -- -9% -69%
roboticus 26595/s 23% 10% -- -65%
GrandFather2 76965/s 256% 218% 189% --
####
use warnings;
use strict;
use Benchmark qw(cmpthese);
print 'checkUPCGrandFather1: ' . checkUPCGrandFather1('064200115897') . "\n";
print 'checkUPCGrandFather2: ' . checkUPCGrandFather2('064200115897') . "\n";
print 'checkUPCroboticus: ' . checkUPCroboticus('064200115897') . "\n";
print 'checkUPCEvanK: ' . checkUPCEvanK('064200115897') . "\n";
cmpthese (-1,
{
GrandFather1 => sub {checkUPCGrandFather1 ('064200115897')},
GrandFather2 => sub {checkUPCGrandFather2 ('064200115897')},
roboticus => sub {checkUPCroboticus ('064200115897')},
EvanK => sub {checkUPCEvanK ('064200115897')},
}
);
sub checkUPCEvanK
{
# grab and immediately split upc into array, 1 char per element
my @chars = split(//, shift);
# return error message if incorrect length
if( $#chars != 11 )
{ return "should be 12 digits in length"; }
my ($odd, $even);
# loop through to seperately sum even and odd chars
foreach (0..10)
{
if($_ % 2 == 0)
{ $odd += $chars[$_]; }
else
{ $even += $chars[$_]; }
}
# calculate correct check digit
my $mult = my $check = ($odd * 3) + $even;
while($mult % 10 != 0)
{ $mult++; }
$check = $mult-$check;
# return error message if wrong check digit was initially given
if($check != $chars[11])
{ return "invalid checkdigit...should be $check"; }
# otherwise, if validated, return undefined
return;
}
# returns error message on failure, undefined value on success
sub checkUPCroboticus
{
# grab and immediately split upc into array, 1 char per element
my @chars = split //, shift;
# return error message if incorrect length
return "should be 12 digits in length" if $#chars != 11;
my ($even, $odd, $check);
foreach (0..5) {
$odd += shift @chars;
$check = shift @chars;
$even += $check;
}
my $mult = 3*$odd+$even-$check;
my $chk2 = 10 - ($mult%10);
return "invalid checkdigit...should be $chk2" if $check!=$chk2;
}
sub checkUPCGrandFather1 {
# grab and immediately split upc into array, 1 char per element
my @chars = split //, shift;
return "should be 12 digits in length" if @chars != 12;
local $| = 0;
my $sum = 0;
# loop through to sum even and adjusted odd chars
$sum += $chars[$_] * (--$| ? 3 : 1) foreach 0..10;
# calculate correct check digit
my $check = (10 - $sum % 10) % 10;
# return error message if wrong check digit was initially given
return $check != $chars[11] ? "invalid checkdigit...should be $check" : undef;
}
sub checkUPCGrandFather2 {
my $str = shift;
return "should be 12 digits in length" if length ($str) != 12;
my $t = 0;
my $sum = 0;
# loop through to sum even and adjusted odd chars
for (0..10) {
my $chr = substr $str, $_, 1;
$sum += ($t ^= 1) ? $chr * 3 : $chr;
}
# calculate correct check digit
my $check = (10 - $sum % 10) % 10;
# return error message if wrong check digit was initially given
return ($check != substr $str, 11) ? "invalid checkdigit...should be $check" : 'Ok';
}