mirror of
https://hub.njuu.cf/TheAlgorithms/Python.git
synced 2023-10-11 13:06:12 +08:00
Add credit card string validator (#5583)
* Add credit card validator * * Add return type hint * Add test cases for validator function * Add test cases * Feature: Rename file * Update strings/cc_validator.py Co-authored-by: Christian Clauss <cclauss@me.com> * Update strings/cc_validator.py Co-authored-by: Christian Clauss <cclauss@me.com> * Update strings/cc_validator.py Co-authored-by: Christian Clauss <cclauss@me.com> * Review: Fix redundant checks * Review: Refactor * Fix: Update test cases * Refactor * Update credit_card_validator.py Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
parent
74e442e979
commit
12e81ea6a2
105
strings/credit_card_validator.py
Normal file
105
strings/credit_card_validator.py
Normal file
@ -0,0 +1,105 @@
|
||||
"""
|
||||
Functions for testing the validity of credit card numbers.
|
||||
|
||||
https://en.wikipedia.org/wiki/Luhn_algorithm
|
||||
"""
|
||||
|
||||
|
||||
def validate_initial_digits(credit_card_number: str) -> bool:
|
||||
"""
|
||||
Function to validate initial digits of a given credit card number.
|
||||
>>> valid = "4111111111111111 41111111111111 34 35 37 412345 523456 634567"
|
||||
>>> all(validate_initial_digits(cc) for cc in valid.split())
|
||||
True
|
||||
>>> invalid = "32323 36111111111111"
|
||||
>>> all(validate_initial_digits(cc) is False for cc in invalid.split())
|
||||
True
|
||||
"""
|
||||
if len(credit_card_number) < 2:
|
||||
return False
|
||||
return credit_card_number[0] in "456" or credit_card_number[1] in "457"
|
||||
|
||||
|
||||
def luhn_validation(credit_card_number: str) -> bool:
|
||||
"""
|
||||
Function to luhn algorithm validation for a given credit card number.
|
||||
>>> luhn_validation('4111111111111111')
|
||||
True
|
||||
>>> luhn_validation('36111111111111')
|
||||
True
|
||||
>>> luhn_validation('41111111111111')
|
||||
False
|
||||
"""
|
||||
cc_number = credit_card_number
|
||||
total = 0
|
||||
half_len = len(cc_number) - 2
|
||||
for i in range(half_len, -1, -2):
|
||||
# double the value of every second digit
|
||||
digit = int(cc_number[i])
|
||||
digit *= 2
|
||||
# If doubling of a number results in a two digit number
|
||||
# i.e greater than 9(e.g., 6 × 2 = 12),
|
||||
# then add the digits of the product (e.g., 12: 1 + 2 = 3, 15: 1 + 5 = 6),
|
||||
# to get a single digit number.
|
||||
if digit > 9:
|
||||
digit %= 10
|
||||
digit += 1
|
||||
cc_number = cc_number[:i] + str(digit) + cc_number[i + 1 :]
|
||||
total += digit
|
||||
|
||||
# Sum up the remaining digits
|
||||
for i in range(len(cc_number) - 1, -1, -2):
|
||||
total += int(cc_number[i])
|
||||
|
||||
return total % 10 == 0
|
||||
|
||||
|
||||
def validate_credit_card_number(credit_card_number: str) -> bool:
|
||||
"""
|
||||
Function to validate the given credit card number.
|
||||
>>> validate_credit_card_number('4111111111111111')
|
||||
4111111111111111 is a valid credit card number.
|
||||
True
|
||||
>>> validate_credit_card_number('helloworld$')
|
||||
helloworld$ is an invalid credit card number because it has nonnumerical characters.
|
||||
False
|
||||
>>> validate_credit_card_number('32323')
|
||||
32323 is an invalid credit card number because of its length.
|
||||
False
|
||||
>>> validate_credit_card_number('32323323233232332323')
|
||||
32323323233232332323 is an invalid credit card number because of its length.
|
||||
False
|
||||
>>> validate_credit_card_number('36111111111111')
|
||||
36111111111111 is an invalid credit card number because of its first two digits.
|
||||
False
|
||||
>>> validate_credit_card_number('41111111111111')
|
||||
41111111111111 is an invalid credit card number because it fails the Lhun check.
|
||||
False
|
||||
"""
|
||||
error_message = f"{credit_card_number} is an invalid credit card number because"
|
||||
if not credit_card_number.isdigit():
|
||||
print(f"{error_message} it has nonnumerical characters.")
|
||||
return False
|
||||
|
||||
if not 13 <= len(credit_card_number) <= 16:
|
||||
print(f"{error_message} of its length.")
|
||||
return False
|
||||
|
||||
if not validate_initial_digits(credit_card_number):
|
||||
print(f"{error_message} of its first two digits.")
|
||||
return False
|
||||
|
||||
if not luhn_validation(credit_card_number):
|
||||
print(f"{error_message} it fails the Lhun check.")
|
||||
return False
|
||||
|
||||
print(f"{credit_card_number} is a valid credit card number.")
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
validate_credit_card_number("4111111111111111")
|
||||
validate_credit_card_number("32323")
|
Loading…
Reference in New Issue
Block a user