*This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)*

This week‘s first task is simple: validate ISBN-13 codes.

ISBNs have been around for a long time and come in many different flavours. ISBN-13 is a thirteen-digit code consisting of twelve digits plus a check digit. The checksum calculation is simple. Given the digits x_{1}, x_{2}, …, x_{12}, and the check digit, x_{13}:

(10 – (x_{1} + 3x_{2} + x_{3} + 3x_{4} + … + x_{11} + 3x_{12} + x_{13})) ≡ 0 (mod 10)

To make calculation a little easier, we can move the check digit (x_{13}) out of the sum and compare it at the end. For example, given the code 978-0-306-40615-7, we can calculate:

10 – (9 + 3×7 + 8 + 3×0 + 3 + 3×0 + 6 + 3×4 + 0 + 3×6 + 1 + 3×5) % 10) = 7

Using `List::Util`

‘s `pairmap`

function, we can simplify the calculation significantly:

```
10 - (sum pairmap { $a + 3*$b } @digits) % 10 == $check;
```

Most of the function is just error checking and input filtering, which could be improved:

```
sub valid_isbn13 {
local $_ = shift;
croak "Invalid ISBN" unless /^[0-9-]+$/;
my @digits = grep { /\d/ } split //;
croak "Only 13 digit ISBNs are supported" if @digits != 13;
my $check = pop @digits;
# Sum of every odd number plus 3 x every even number
10 - (sum pairmap { $a + 3*$b } @digits) % 10 == $check;
}
```