Skip to content

Commit d259f7d

Browse files
authored
Merge pull request #111 from ikostan/exercism-sync/6a8574709146f471
[Sync Iteration] python/isbn-verifier/4
2 parents 898ffd7 + 6664142 commit d259f7d

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
ISBN Verifier.
3+
4+
The ISBN-10 verification process is used to validate book identification
5+
numbers. These normally contain dashes and look like: 3-598-21508-8
6+
7+
ISBN
8+
The ISBN-10 format is 9 digits (0 to 9) plus one check character
9+
(either a digit or an X only). In the case the check character is an X,
10+
this represents the value '10'. These may be communicated with or without
11+
hyphens, and can be checked for their validity by the following formula:
12+
13+
(d₁ * 10 + d₂ * 9 + d₃ * 8 + d₄ * 7 + d₅ * 6 +
14+
d₆ * 5 + d₇ * 4 + d₈ * 3 + d₉ * 2 + d₁₀ * 1) mod 11 == 0
15+
16+
If the result is 0, then it is a valid ISBN-10, otherwise it is invalid.
17+
"""
18+
19+
ISBN: str = "0123456789X"
20+
21+
22+
def formatted_isbn(isbn: str) -> list[int]:
23+
"""
24+
Extract and format ISBN digits from input string.
25+
26+
Converts ISBN string to list of integers, treating 'X' as 10.
27+
Ignores non-digit characters except for trailing 'X'.
28+
29+
:param isbn: ISBN string that may contain digits, hyphens, and trailing 'X'
30+
:return: List of integers representing ISBN digits, 'X' converted to 10
31+
"""
32+
result: list[int] = []
33+
for char in isbn:
34+
if char.isdigit():
35+
result.append(int(char))
36+
if isbn[-1].lower() == "x":
37+
result.append(10)
38+
39+
print(f"result: {result}, len: {len(result)}")
40+
return result
41+
42+
43+
def is_valid(isbn: str) -> bool:
44+
"""
45+
Verify ISBN.
46+
47+
:param isbn: 9 digits ISBN 10 format
48+
:return: Tru if isbn is valid, False otherwise
49+
"""
50+
# Non ISBN chars or empty strings not allowed
51+
if not all(char in ISBN for char in isbn.replace("-", "")) or not isbn:
52+
return False
53+
# In case X is present, it should be at the end of the string only
54+
if 'X' in isbn and isbn.index('X') != len(isbn) - 1:
55+
return False
56+
57+
# Convert all isbn chars to digits
58+
isbn_digits: list[int] = formatted_isbn(isbn)
59+
# ISBN total length should be = 10
60+
if len(isbn_digits) != 10:
61+
return False
62+
63+
return (
64+
sum(digit * (10 - i) for i, digit in enumerate(isbn_digits)) % 11 == 0
65+
)

0 commit comments

Comments
 (0)