I\'m given some ISBN numbers e.g. 3-528-03851
(not valid) , 3-528-16419-0
(valid). I\'m supposed to write a program which tests if the ISBN number
First, try to avoid code like this:
if Action():
lots of code
return True
return False
Flip it around, so the bulk of code isn't nested. This gives us:
def check(isbn):
check_digit = int(isbn[-1])
match = re.search(r'(\d)-(\d{3})-(\d{5})', isbn[:-1])
if not match:
return False
digits = match.group(1) + match.group(2) + match.group(3)
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
There are some bugs in the code:
So, let's simplify this. First, remove all spaces and hyphens, and make sure the regex matches the whole line by bracing it in '^...$'. That makes sure it rejects strings which are too long.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "");
check_digit = int(isbn[-1])
match = re.search(r'^(\d{9})$', isbn[:-1])
if not match:
return False
digits = match.group(1)
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
Next, let's fix the "X" check digit problem. Match the check digit in the regex as well, so the entire string is validated by the regex, then convert the check digit correctly.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "").upper();
match = re.search(r'^(\d{9})(\d|X)$', isbn)
if not match:
return False
digits = match.group(1)
check_digit = 10 if match.group(2) == 'X' else int(match.group(2))
result = 0
for i, digit in enumerate(digits):
result += (i + 1) * int(digit)
return True if (result % 11) == check_digit else False
Finally, using a generator expression and max
is a more idiomatic way of doing the final calculation in Python, and the final conditional can be simplified.
def check(isbn):
isbn = isbn.replace("-", "").replace(" ", "").upper();
match = re.search(r'^(\d{9})(\d|X)$', isbn)
if not match:
return False
digits = match.group(1)
check_digit = 10 if match.group(2) == 'X' else int(match.group(2))
result = sum((i + 1) * int(digit) for i, digit in enumerate(digits))
return (result % 11) == check_digit