Skip to main content

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, and 978 0 471 48648 0 are all equivalent.
  • The check digit is calculated by:
    1. Multiplying each of the first 12 digits alternately by 1 and 3 (1st digit × 1, 2nd × 3, 3rd × 1, 4th × 3, …).
    2. Summing those products.
    3. Taking that sum modulo 10.
    4. Subtracting the result from 10.
    5. Taking the result of that modulo 10 again, to fold a result of 10 down to 0.
  • The function returns true only 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"));
}