-3

I have been assigned to create a function that takes 9 numbers and returns the 10th as if it were an ISBN number. I will include the exact directions at the bottom, but, in summary, the last digit must be the sum of the other 9 digits, with the first digit being multiplied by 1, the second by 2, and so on.

Here is what I have so far:

def isbn_gendigit(isbn):
    '''
    docstring (fill in later)
    '''
    length = 9
    last_digit = 0
    last_digit = int(isbn[0]) * (length)
    for i in range(len(isbn)):
        length - 1
    isbn = isbn % 11
    last_digit = 11 - isbn
    print(ISBN + last_digit)
    return None

I know it is far from done and perfect, but I'm having troubles understanding how to approach the problem. I've looked at other similar ISBN-based problems on here, but the few that I saw are far more complex than what I am looking for.


Project Directions: ISBN Check Digits

The International Standard Book Number (ISBN) is (prior to 2007) a 10-digit code that uniquely specifies a book. The rightmost digit is a checksum digit which can be uniquely determined from the other 9 digits from the condition that d1 + 2d2 + 3d3 + ... + 10d10 must be a multiple of 11 (here di denotes the ith digit from the right).

Example: the checksum digit corresponding to 020131452d10 is the only value of d10 is between 0 and 10 – and that would be: 1*0 + 2*2 + 3*0 + 4*1 + 5*3 + 6*1 + 7*4 + 8*5 + 9*2 + 10*d10 which is a multiple of 11.

To calculate d10: Find 1*0 + 2*2 + 3*0 + 4*1 + 5*3 + 6*1 + 7*4 + 8*5 + 9*2) = 115 then find the remainder of 115%11 = 5 which is the value of the10th digit d10 = 5. So, the 10 digit ISBN is now 0201314525 - and we can check and see that (115+10*5)%11 = 0 is true.

Using the function design recipe, define a Python function, isbn_gendigit, with one parameter, isbn, a 9-digit string. The function should compute the check digit for a given ISBN, and then print out the 10-digit ISBN. isbn_gendigit will return the value None (end of the function, type “return None”).

Test your function on the following examples:

isbn_gendigit('020131452')

0201314525

isbn_gendigit('068131921')

0681319216


PaSTE
  • 4,050
  • 18
  • 26

1 Answers1

3

You're given the algorithm in the problem, which is nice:

To calculate d10: Find (1*0 + 2*2 + 3*0 + 4*1 + 5*3 + 6*1 + 7*4 + 8*5 + 9*2) = 115 then find the remainder of 115%11 = 5 which is the value of the10th digit d10 = 5

All you have to do is convert that to Python.

Simple for loop

Your solution is not implementing the algorithm properly. What is length doing? All you have to do is iterate from the beginning (left side) of the string to the end (right side), keeping track of the index into the string as you go:

def isbn_gendigit(isbn):
    total = 0
    for i in range(len(isbn)): # iterates from 0 to the length of the string (minus 1)
        n = isbn[i]            # the ith character in the string
        num = int(n)           # convert to an integer
        total += (i+1) * num   # sum the digit times the increment
    d10 = total % 11           # modulo 11
    print(isbn + str(d10))     # print the result
    return None                # return None (technically not needed)

Iterating over strings

We can do better. First of all, strings in Python are iterable. Why does this matter? Because, per the specs, we are given a string:

...define a Python function, isbn_gendigit, with one parameter, isbn, a 9-digit string.

This makes iteration over the input value a breeze, but it does mean we have to keep track of the index into the string as a separate variable i:

def isbn_gendigit(isbn):
    total = 0
    i = 0
    for n in isbn:         # iterating over the string gives each character of the string in order
        num = int(n)       # convert to an integer
        i += 1             # increment the digit index
        total += i * num   # sum the digit times the increment
    d10 = total % 11       # modulo 11
    print(isbn + str(d10)) # print the result
    return None            # return None (technically not needed)

Enumerating strings

We can still do better. In fact, we can get both the digit and its position in the string by iterating using Python's built-in enumerate function, obviating the need to manually keep track of the index i:

def isbn_gendigit(isbn):
    total = 0
    for i, n in enumerate(isbn): # now I have a number and a character
        num = int(n)             # convert to a number
        total += (i+1) * num     # sum the digits
    d10 = total % 11             # modulo 11
    print(isbn + str(d10))       # print the result
    return None                  # return None (technically not needed)

Generator expressions

Of course, we can do even better than this. Using generator expressions and the built-in sum function, we can turn this for-loop sum into a one-liner:

def isbn_gendigit(isbn):
    # multiply and sum everything at once
    total = sum((i+1) * int(n) for i, n in enumerate(isbn))
    d10 = total % 11        # modulo 11
    print(isbn + str(d10))  # print the result
    return None             # return None (technically not needed)
PaSTE
  • 4,050
  • 18
  • 26
  • This is fantastic! I really appreciate how you broke it down step by step. IDLE didn't like the line "print(isbn + d10)," although "print(str(isbn) + str(d10))" seems to work just fine. Thank you! – Karen Steele Feb 08 '18 at 01:34
  • Thanks for pointing that out. Adding strings and integers doesn't make sense. I have updated my answer to correct this. – PaSTE Feb 08 '18 at 02:13