Skip to content

Commit 12e81ea

Browse files
Add credit card string validator (TheAlgorithms#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>
1 parent 74e442e commit 12e81ea

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

strings/credit_card_validator.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""
2+
Functions for testing the validity of credit card numbers.
3+
4+
https://en.wikipedia.org/wiki/Luhn_algorithm
5+
"""
6+
7+
8+
def validate_initial_digits(credit_card_number: str) -> bool:
9+
"""
10+
Function to validate initial digits of a given credit card number.
11+
>>> valid = "4111111111111111 41111111111111 34 35 37 412345 523456 634567"
12+
>>> all(validate_initial_digits(cc) for cc in valid.split())
13+
True
14+
>>> invalid = "32323 36111111111111"
15+
>>> all(validate_initial_digits(cc) is False for cc in invalid.split())
16+
True
17+
"""
18+
if len(credit_card_number) < 2:
19+
return False
20+
return credit_card_number[0] in "456" or credit_card_number[1] in "457"
21+
22+
23+
def luhn_validation(credit_card_number: str) -> bool:
24+
"""
25+
Function to luhn algorithm validation for a given credit card number.
26+
>>> luhn_validation('4111111111111111')
27+
True
28+
>>> luhn_validation('36111111111111')
29+
True
30+
>>> luhn_validation('41111111111111')
31+
False
32+
"""
33+
cc_number = credit_card_number
34+
total = 0
35+
half_len = len(cc_number) - 2
36+
for i in range(half_len, -1, -2):
37+
# double the value of every second digit
38+
digit = int(cc_number[i])
39+
digit *= 2
40+
# If doubling of a number results in a two digit number
41+
# i.e greater than 9(e.g., 6 × 2 = 12),
42+
# then add the digits of the product (e.g., 12: 1 + 2 = 3, 15: 1 + 5 = 6),
43+
# to get a single digit number.
44+
if digit > 9:
45+
digit %= 10
46+
digit += 1
47+
cc_number = cc_number[:i] + str(digit) + cc_number[i + 1 :]
48+
total += digit
49+
50+
# Sum up the remaining digits
51+
for i in range(len(cc_number) - 1, -1, -2):
52+
total += int(cc_number[i])
53+
54+
return total % 10 == 0
55+
56+
57+
def validate_credit_card_number(credit_card_number: str) -> bool:
58+
"""
59+
Function to validate the given credit card number.
60+
>>> validate_credit_card_number('4111111111111111')
61+
4111111111111111 is a valid credit card number.
62+
True
63+
>>> validate_credit_card_number('helloworld$')
64+
helloworld$ is an invalid credit card number because it has nonnumerical characters.
65+
False
66+
>>> validate_credit_card_number('32323')
67+
32323 is an invalid credit card number because of its length.
68+
False
69+
>>> validate_credit_card_number('32323323233232332323')
70+
32323323233232332323 is an invalid credit card number because of its length.
71+
False
72+
>>> validate_credit_card_number('36111111111111')
73+
36111111111111 is an invalid credit card number because of its first two digits.
74+
False
75+
>>> validate_credit_card_number('41111111111111')
76+
41111111111111 is an invalid credit card number because it fails the Lhun check.
77+
False
78+
"""
79+
error_message = f"{credit_card_number} is an invalid credit card number because"
80+
if not credit_card_number.isdigit():
81+
print(f"{error_message} it has nonnumerical characters.")
82+
return False
83+
84+
if not 13 <= len(credit_card_number) <= 16:
85+
print(f"{error_message} of its length.")
86+
return False
87+
88+
if not validate_initial_digits(credit_card_number):
89+
print(f"{error_message} of its first two digits.")
90+
return False
91+
92+
if not luhn_validation(credit_card_number):
93+
print(f"{error_message} it fails the Lhun check.")
94+
return False
95+
96+
print(f"{credit_card_number} is a valid credit card number.")
97+
return True
98+
99+
100+
if __name__ == "__main__":
101+
import doctest
102+
103+
doctest.testmod()
104+
validate_credit_card_number("4111111111111111")
105+
validate_credit_card_number("32323")

0 commit comments

Comments
 (0)