"use strict"; function isbn10CheckDigit(nine) { let sum = 0; for (let i = 0; i < 9; i++) sum += Number(nine[i]) * (10 - i); const rem = sum % 11; const check = (11 - rem) % 11; return check === 10 ? "X" : String(check); } function isbn10Validate(ten) { let sum = 0; for (let i = 0; i < 10; i++) { const ch = ten[i]; const v = ch === "X" || ch === "x" ? 10 : Number(ch); sum += v * (10 - i); } return sum % 11 === 0; } function isbn13CheckDigit(twelve) { let sum = 0; for (let i = 0; i < 12; i++) sum += Number(twelve[i]) * (i % 2 === 0 ? 1 : 3); const rem = sum % 10; return String((10 - rem) % 10); } function isbn13Validate(thirteen) { let sum = 0; for (let i = 0; i < 13; i++) sum += Number(thirteen[i]) * (i % 2 === 0 ? 1 : 3); return sum % 10 === 0; } module.exports = { slug: "isbn-10-and-13-check-digit", title: "ISBN-10 / ISBN-13 check digit", deck_category: "other", description: "Validates an ISBN-10 or ISBN-13, or computes its check digit, per the ISBN standard.", inputs: [ { name: "isbn_type", type: "string", required: true, description: "Which ISBN format.", enum: ["isbn10", "isbn13"] }, { name: "operation", type: "string", required: true, description: "Whether to validate a full ISBN or compute a missing check digit.", enum: ["validate", "compute"] }, { name: "digits", type: "string", required: true, description: "For validate: the full 10 or 13 characters (ISBN-10 may end in X). For compute: the first 9 (isbn10) or 12 (isbn13) digits." } ], outputs: [ { name: "result", description: "For validate: true or false. For compute: the check digit/character." } ], steps: [ "ISBN-10: weight the 10 digits 10,9,8,...,1 (left to right); the sum of digit*weight must be a multiple of 11 for a valid ISBN. The check digit (10th digit) can be 'X', representing 10.", "To compute an ISBN-10 check digit from the first 9 digits: sum digit_i*(10-i) for i=0..8, then check = (11 - (sum mod 11)) mod 11; if check is 10, use 'X'.", "ISBN-13: weight the 13 digits alternately 1,3,1,3,...,1 (left to right); the sum of digit*weight must be a multiple of 10 for a valid ISBN.", "To compute an ISBN-13 check digit from the first 12 digits: sum digit_i*(1 if i even else 3) for i=0..11, then check = (10 - (sum mod 10)) mod 10." ], constants: [], sources: [ { kind: "standard", value: "ISO 2108:2017, Information and documentation - International Standard Book Number (ISBN).", title: "ISO 2108 (the ISBN standard)", publisher: "ISO", retrieved_utc: "2026-09-30T20:02:00Z", note: "Defines the ISBN-10 modulus-11 and ISBN-13 modulus-10 (EAN-13) check digit schemes." } ], disclaimer: null, questionText(inputs) { if (inputs.operation === "validate") return `Is ${inputs.digits} a valid ${inputs.isbn_type === "isbn10" ? "ISBN-10" : "ISBN-13"}?`; return `What is the ${inputs.isbn_type === "isbn10" ? "ISBN-10" : "ISBN-13"} check digit for ${inputs.digits}?`; }, run(inputs) { const { isbn_type, operation, digits } = inputs || {}; if (isbn_type !== "isbn10" && isbn_type !== "isbn13") throw new Error("isbn_type must be isbn10 or isbn13"); if (operation !== "validate" && operation !== "compute") throw new Error("operation must be validate or compute"); if (typeof digits !== "string") throw new Error("digits must be a string"); if (isbn_type === "isbn10") { if (operation === "compute") { if (!/^\d{9}$/.test(digits)) throw new Error("digits must be exactly 9 numeric characters for isbn10 compute"); const check = isbn10CheckDigit(digits); return { answer: check, values: { result: check } }; } if (!/^\d{9}[\dXx]$/.test(digits)) throw new Error("digits must be exactly 10 characters (last may be X) for isbn10 validate"); const valid = isbn10Validate(digits.toUpperCase()); return { answer: `${valid}`, values: { result: valid } }; } if (operation === "compute") { if (!/^\d{12}$/.test(digits)) throw new Error("digits must be exactly 12 numeric characters for isbn13 compute"); const check = isbn13CheckDigit(digits); return { answer: check, values: { result: Number(check) } }; } if (!/^\d{13}$/.test(digits)) throw new Error("digits must be exactly 13 numeric characters for isbn13 validate"); const valid = isbn13Validate(digits); return { answer: `${valid}`, values: { result: valid } }; }, examples: [ { name: "worked example", inputs: { isbn_type: "isbn10", operation: "compute", digits: "020161622" }, expected: { answer: "X" }, check: "020161622 is the first 9 digits of the published ISBN 0-201-61622-X for 'The C Programming Language'; by hand, sum = 0*10+2*9+0*8+1*7+6*6+1*5+6*4+2*3+2*2 = 100, 100 mod 11 = 1, check = (11-1) mod 11 = 10 = X, matching the real published ISBN." }, { name: "test vector: ISBN-13 validate", inputs: { isbn_type: "isbn13", operation: "validate", digits: "9780306406157" }, expected: { answer: "true" }, check: "9780306406157 is the widely published valid ISBN-13 example used to illustrate the EAN-13 check; by hand the weighted sum (weights 1,3 alternating) totals 100, a multiple of 10, so it is valid." } ] };