Your function considers an input string as valid, if (after sanitizing) it either matches a certain regex, or passes a certain check digit algorithm.

There are many standardized check digit algorithms in use; if you need to find out which one you're dealing with here, maybe this Wikipedia page can help.
Edit: As it turns out, it's the Luhn algorithm.

Anyway, here is a more or less literal translation of your code to to Perl with many explanatory comments (keeping in mind that I had to make an educated guess about the non-standard function discussed in a separate answer above):

#!/usr/bin/perl use strict; use warnings; use feature 'say'; sub validate_serial_number { my $v = shift; $v =~ s/\s//g; # remove whitespace $v = uc $v; # convert to uppercase # 1) Try regex: return 0 if !length $v; return 1 if $v =~ /^JM-\d+-\S{4}[1-9Zz]{6}$/; # 2) Initialize the %map hash with (A=>0, B=>1, C=>2, ...): my $dv = 0; my %map = map { $_ => $dv++ } qw(A B C D E F G H J K L M N P Q R T U V W Y 3 4 6 7 8 9); # 3) Extract significant character data, for example: # 'FOOBAR123ABCDE' -> chars: qw(D C B A 3 R A B F) # check: 'E' my @chars = reverse split '', $v; my $check = shift @chars; @chars = grep { exists $map{$_} } @chars; # 4) Sanity check: return 0 if @chars != 9; # 5) Perform check digit algorithm: my $totalVal = 0; # Loop over the reversed array of input characters: for my $i (0..$#chars) { # Map the character to a unique numeric value: my $posVal = $map{$chars[$i]}; # Double the value, but only for every second character: $posVal *= 2 if !($i % 2); # Add the sum of the digits of $posVal to $totalVal: while($posVal){ $totalVal += $posVal % 10; $posVal = int($posVal / 10); } } # Substract the last digit of $totalVal from 10, and take the # last digit of *that* to get the check digit: return ( $check eq ( 10 - $totalVal % 10 ) % 10 ); } for ('Foo abr 123 ABCD6', 'Foo bar 123 ABCD6') { say "'$_' is " . (validate_serial_number($_) ? "valid" : "invalid"); }

Output:

'Foo abr 123 ABCD6' is invalid 'Foo bar 123 ABCD6' is valid

In reply to Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl by smls
in thread I'm struggling with a function, and hoping for some insight -- not strictly Perl by taint

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.