# PWC 162 › ISBN-13

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 x1, x2, …, x12, and the check digit, x13:

(10 – (x1 + 3x2 + x3 + 3x4 + … + x11 + 3x12 + x13)) ≡ 0 (mod 10)

To make calculation a little easier, we can move the check digit (x13) 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;
}
```