ISBN-13 Validation
The challenge
Write a function that takes a string and returns whether it is a valid ISBN-13 (the barcode number found on the back of most books).
- ISBN-13 is 12 digits plus a check digit (13 digits total).
- Spaces and hyphens may appear in the input but are not significant, so
9780471486480,978-0-471-48648-0, and978 0 471 48648 0are all equivalent. - The check digit is calculated by:
- Multiplying each of the first 12 digits alternately by
1and3(1st digit × 1, 2nd × 3, 3rd × 1, 4th × 3, …). - Summing those products.
- Taking that sum modulo 10.
- Subtracting the result from 10.
- Taking the result of that modulo 10 again, to fold a result of 10 down to 0.
- Multiplying each of the first 12 digits alternately by
- The function returns
trueonly if the calculated check digit matches the 13th digit of the input.
Valid examples: 9780470059029, 978 0 471 48648 0, 978-0596809485, 978-0-13-149505-0, 978-0-262-13472-9.
Remember to follow the red-green-refactor cycle and, if you're using an AI coding assistant, keep it on a tight leash — one test at a time.
Suggested test list
- A known valid ISBN-13 with no spaces or hyphens →
true(happy path). - The same ISBN-13 with hyphens inserted →
true. - The same ISBN-13 with spaces inserted →
true. - A valid ISBN-13 with the last (check) digit changed →
false. - A string of exactly 13 digits that doesn't satisfy the checksum →
false. - A string with only 12 digits (too short) →
false. - A string with 14 digits (too long) →
false. - A 13-character string that contains a letter or other non-digit character →
false. - An empty string →
false. - A string that's nothing but separators (e.g.
"- - - -") →false.
Your task
Implement the solution using strict TDD, one test from the list at a time.
💡 Show a reference solution (only after you've completed your own via TDD)
public class Isbn13Validator {
public static boolean isValid(String input) {
String digits = input.replaceAll("[ -]", "");
if (!digits.matches("\\d{13}")) {
return false;
}
int sum = 0;
for (int i = 0; i < 12; i++) {
int digit = digits.charAt(i) - '0';
sum += (i % 2 == 0) ? digit : digit * 3;
}
int checkDigit = (10 - (sum % 10)) % 10;
int lastDigit = digits.charAt(12) - '0';
return checkDigit == lastDigit;
}
}
// example tests, e.g. with JUnit 5
@Test
void validIsbnWithNoSeparators() {
assertTrue(Isbn13Validator.isValid("9780470059029"));
}
@Test
void validIsbnWithHyphens() {
assertTrue(Isbn13Validator.isValid("978-0-471-48648-0"));
}
@Test
void invalidCheckDigit() {
assertFalse(Isbn13Validator.isValid("9780470059020"));
}
@Test
void tooShort() {
assertFalse(Isbn13Validator.isValid("978047005902"));
}