Luhn check a card number
Before a card ever reaches the payment gateway, the checkout runs the Luhn checksum so an obvious typo is caught in the browser.
- Working from the right, double every second digit; if doubling gives more than 9, subtract 9.
- The number is valid when the resulting sum divides by 10.
- Spaces and dashes are formatting and are ignored.
- Any other non-digit makes it invalid, as does anything shorter than two digits.
luhn_valid(digits: string) → bool
Where you start
def luhn_valid(digits: str) -> bool:
Worked examples
| Call | Result |
|---|---|
luhn_valid("79927398713") | True |
luhn_valid("79927398710") | False |
luhn_valid("4111 1111 1111 1111") | True |
luhn_valid("4111-1111-1111-1112") | False |
Hint
Strip the formatting into a clean string first. Then walk it backwards with an index so "every second" is easy to say.
Reference solution in Python
def luhn_valid(digits: str) -> bool:
clean = ''
for c in digits:
if c in ' -':
continue
if not c.isdigit():
return False
clean += c
if len(clean) < 2:
return False
total = 0
for i, c in enumerate(reversed(clean)):
d = int(c)
if i % 2 == 1:
d *= 2
if d > 9:
d -= 9
total += d
return total % 10 == 0