Problem: ISBN
Questions? Feel free to head to CS50 on Reddit, CS50 on StackExchange, or the CS50 Facebook group.
Objectives

Use algorithms to solve problems.

Learn about checksums.

See how to manipulate a large piece of data to create meaningful pieces from it.
Recommended Reading

Pages 1 – 7, 9, and 10 of http://www.howstuffworks.com/c.htm.

Chapters 1 – 5, 9, and 11 – 17 of Absolute Beginner’s Guide to C.

Chapters 1 – 6 of Programming in C.
Academic Honesty
This course’s philosophy on academic honesty is best stated as "be reasonable." The course recognizes that interactions with classmates and others can facilitate mastery of the course’s material. However, there remains a line between enlisting the help of another and submitting the work of another. This policy characterizes both sides of that line.
The essence of all work that you submit to this course must be your own. Collaboration on problems is not permitted (unless explicitly stated otherwise) except to the extent that you may ask classmates and others for help so long as that help does not reduce to another doing your work for you. Generally speaking, when asking for help, you may show your code or writing to others, but you may not view theirs, so long as you and they respect this policy’s other constraints. Collaboration on quizzes and tests is not permitted at all. Collaboration on the final project is permitted to the extent prescribed by its specification.
Below are rules of thumb that (inexhaustively) characterize acts that the course considers reasonable and not reasonable. If in doubt as to whether some act is reasonable, do not commit it until you solicit and receive approval in writing from your instructor. If a violation of this policy is suspected and confirmed, your instructor reserves the right to impose local sanctions on top of any disciplinary outcome that may include an unsatisfactory or failing grade for work submitted or for the course itself.
Reasonable

Communicating with classmates about problems in English (or some other spoken language).

Discussing the course’s material with others in order to understand it better.

Helping a classmate identify a bug in his or her code, such as by viewing, compiling, or running his or her code, even on your own computer.

Incorporating snippets of code that you find online or elsewhere into your own code, provided that those snippets are not themselves solutions to assigned problems and that you cite the snippets' origins.

Reviewing past years' quizzes, tests, and solutions thereto.

Sending or showing code that you’ve written to someone, possibly a classmate, so that he or she might help you identify and fix a bug.

Sharing snippets of your own solutions to problems online so that others might help you identify and fix a bug or other issue.

Turning to the web or elsewhere for instruction beyond the course’s own, for references, and for solutions to technical difficulties, but not for outright solutions to problems or your own final project.

Whiteboarding solutions to problems with others using diagrams or pseudocode but not actual code.

Working with (and even paying) a tutor to help you with the course, provided the tutor does not do your work for you.
Not Reasonable

Accessing a solution to some problem prior to (re)submitting your own.

Asking a classmate to see his or her solution to a problem before (re)submitting your own.

Decompiling, deobfuscating, or disassembling the staff’s solutions to problems.

Failing to cite (as with comments) the origins of code, writing, or techniques that you discover outside of the course’s own lessons and integrate into your own work, even while respecting this policy’s other constraints.

Giving or showing to a classmate a solution to a problem when it is he or she, and not you, who is struggling to solve it.

Looking at another individual’s work during a quiz or test.

Paying or offering to pay an individual for work that you may submit as (part of) your own.

Providing or making available solutions to problems to individuals who might take this course in the future.

Searching for, soliciting, or viewing a quiz’s questions or answers prior to taking the quiz.

Searching for or soliciting outright solutions to problems online or elsewhere.

Splitting a problem’s workload with another individual and combining your work (unless explicitly authorized by the problem itself).

Submitting (after possibly modifying) the work of another individual beyond allowed snippets.

Submitting the same or similar work to this course that you have submitted or will submit to another.

Using resources during a quiz beyond those explicitly allowed in the quiz’s instructions.

Viewing another’s solution to a problem and basing your own solution on it.
Assessment
Your work on this problem set will be evaluated along four axes primarily.
 Scope

To what extent does your code implement the features required by our specification?
 Correctness

To what extent is your code consistent with our specifications and free of bugs?
 Design

To what extent is your code written well (i.e., clearly, efficiently, elegantly, and/or logically)?
 Style

To what extent is your code readable (i.e., commented and indented with variables aptly named)?
To obtain a passing grade in this course, all students must ordinarily submit all assigned problems unless granted an exception in writing by the instructor.
Readin' Bookz
As you may know, most any book that you borrow or buy has an International Standard Book Number, otherwise known as an ISBN or ISBN10, "a 10digit number that uniquely identifies books and booklike products published internationally."^{[1]} Books published since 2007 might also have an ISBN13, a 13digit number with a similar purpose, but never mind those.
It turns out that the last of an ISBN10’s digits is a "check digit," otherwise known (in binary contexts) as a "checksum," a number related mathematically to its preceding digits. ISBN10s' digits are supposed to adhere to a formula, not unlike credit card numbers, and this check digit allows you to check whether an ISBN10’s other nine digits are (most likely) valid without having to check, say, a database of books.
Per the International ISBN Agency’s ISBN Users' Manual, "The check digit is the last digit of an ISBN. It is calculated on a modulus 11 with weights 102, using X in lieu of 10 where ten would occur as a check digit."^{[2]}
Yes rly, but what does that mean? The manual elaborates. "This means that each of the first nine digits of the ISBN—excluding the check digit itself—is multiplied by a number ranging from 10 to 2 and that the resulting sum of the products, plus the check digit, must be divisible by 11 without a remainder."
Okay, better, but still a bit unclear. Let’s define the check digit in terms of a formula. Fortunately, thanks to "modular arithmetic," we can simplify the Agency’s formal definition using weights ranging from 1 to 9 instead of 10 to 2. In fact, it’s really quite simple. If x_{1} represents an ISBN10’s first digit and x_{10} its last^{[3]}, it turns out that:
x_{10} = (1·x_{1} + 2·x_{2} + 3·x_{3} + 4·x_{4} + 5·x_{5} + 6·x_{6} + 7·x_{7} + 8·x_{8} + 9·x_{9}) mod 11
In other words, to compute an ISBN10’s tenth digit, multiply its first digit by 1, its second digit by 2, its third digit by 3, its fourth digit by 4, its fifth digit by 5, its sixth digit by 6, its seventh digit by 7, its eighth digit by 8, and its ninth digit by 9. Take the sum of those products and then divide it
by 11. The remainder should be the ISBN10’s tenth digit! If, though, that remainder is 10, the tenth digit should instead be printed as X
lest it be confused with a 1
followed by 0
.
I S BN Calculatin'
Let’s try all this out. The ISBN10 for the Absolute Beginner’s Guide to C, one of the course’s recommended books, is 0789751984, the tenth digit of which is, obviously, 4. But is the syllabus right? Well, let’s first take that sum using the ISBN10’s first nine digits (highlighted in bold):
1·0 + 2·7 + 3·8 + 4·9 + 5·7 + 6·5 + 7·1 + 8·9 + 9·8 = 290
If we now divide that sum by 11, we get 290 ÷ 11 = 26 4/11 (i.e., a remainder of 4)! Well that’s kind of neat, the ISBN is legit! Actually, also thanks to modular arithmetic, we could just include that tenth digit in our sum and multiply it by 10:
1·0 + 2·7 + 3·8 + 4·9 + 5·7 + 6·5 + 7·1 + 8·9 + 9·8 + 10·4 = 330
If we now divide this sum by 11, we get 330 ÷ 11 = 30 with no remainder at all, which is an equivalent way of saying the ISBN10 is legit! Stated more formally, 0 ≡ 330 (mod 11)!
Hopefully those exclamation points make the math more exciting.
So, computing this check digit’s not hard, but it does get a bit tedious by hand. Let’s write a program.
Create a file called isbn.c
inside of your ~/workspace/chapter1
directory, in which you should write a program that prompts the user for an ISBN10 and then reports (via printf
) whether the number’s legit. So that we can automate some tests of your code, we ask that your program’s last line of output be either YES\n
or NO\n
, nothing more, nothing less.
For simplicity, you may assume that the user’s input will be exactly ten decimal digits (i.e., devoid of hyphens and X
), the first of which might even be zero(es), as in the case of our recommended book. But do not assume that the user’s input will fit in an int
! Recall, after all, that the largest value that can fit in an int
is 2^{32}  1 = 4,294,967,295 (and, even then, only if declared as unsigned
). True, that’s a 10digit value, but there might still be a problem. (What?) Best to be safe and use get_long_long
from CS50’s library to get users' input. (Why?)
Okay, so you’ve gotten some input. What should you do? Well, realize that this C program, not unlike Scratch projects, can be reduced to the most basic of building blocks. For the sake of
discussion, suppose that some variable x
contains a 10digit long long
(with no leading zeroes). How can you get at its tenth (i.e., rightmost) digit? Well how about this?
int tenth = x % 10;
Do you see why that works? Do not pass Go until it dawns on you why!
How, now, can you get at that same variable’s ninth digit? Well, why don’t we first get rid of its tenth digit by shifting every other one place to the right?
x = x / 10;
How about that trick? Do you see why it works? The ninth digit, now, is just:
int ninth = x % 10;
So we bet there’s a pattern here. And odds are you don’t need to (i.e., shouldn’t) copy/paste lines like the above nine or ten times. Loops are your friend. To be sure, other approaches exist. Proceed as you wish! Perhaps some of these tricks, though, will get you started.
To compile your program, type
make isbn
Assuming your program compiled without errors (or, ideally, warnings) via either command, run your program with the command below.
./isbn
Consider the below representative of how your own program should behave when passed a valid ISBN10 (sans hyphens); underlined is some user’s input.
~/workspace/chapter1 $ ./isbn
ISBN: 0789751984
YES
Of course, get_long_long
itself will reject an ISBN10’s hyphens (and more) anyway:
~/workspace/chapter1 $ ./isbn
ISBN: 0789751984
Retry: foo
Retry: 0789751984
YES
But it’s up to you to catch inputs that are not ISBN10s (e.g., Jenny’s^{[4]} phone number), even if ten digits.
~/workspace/chapter1 $ ./isbn
ISBN: 5558675309
NO
Test out your program with a whole bunch of inputs, both valid and invalid. (We certainly will!) There are lots of valid ISBN10s on amazon.com. Of course, you should also test your program with check50
:
check50 1617.chapter1.isbn isbn.c
If your program behaves incorrectly on some inputs (or doesn’t compile at all), have fun debugging! And if you’d like to play with the staff’s own implementation of isbn
on CS50 IDE, you may execute the below.
~cs50/chapter1/isbn
This was ISBN.