$cv{$_} = $i++ for '0'..'9', 'A'..'Z', '*', '@', '

sub cusip_check_digit {
    my @cusip = split m{}xms, shift;
    my $sum = 0;

    for $i (0..7) {
        return 'Invalid character found' unless $cusip[$i] =~ m{\A [[:digit:][:upper:]*@
        $v  = $cv{ $cusip[$i] };
        $v *= 2 if $i%2;
        $sum += int($v/10) + $v%10;
    }

    $check_digit = (10 - ($sum%10)) % 10;
    $check_digit == $cusip[8] ? '' : ' (incorrect)';
}

my %test_data = (
    '037833100' => 'Apple Incorporated',
    '17275R102' => 'Cisco Systems',
    '38259P508' => 'Google Incorporated',
    '594918104' => 'Microsoft Corporation',
    '68389X106' => 'Oracle Corporation',
    '68389X105' => 'Oracle Corporation',
);

print "$_ $test_data{$_}" . cusip_check_digit($_) . "\n" for sort keys %test_data;