import math
def luhns_algorithm(num):
argument_is_integer = isinstance(num, int)
number = num #from this number we will get every other digit
every_other_digit = [] #we will append every other digit to this list
not_every_other_digit = [] #we will append the other digits to this list
every_other_digit_times_two = [] #we will append every other digit multiplied by two to this list
sum_of_digits_in_every_other_digit = 0 #Counter to store the sum of the digits of the numbers in the list
#every_other_digit_times_two
valid = False #The default is that the credit card is not valid. If the last digit of the target sum is 0, the card is valid
rem = 1 #We will use rem in the while loop to get the last digits of the number
target_sum = 0
#Checks that the argument is an integer. If not, the credit card number is not valid.
if argument_is_integer != True:
return
else:
#In the following while loop, the goal is to split the digits of the number in two halves and store those
#halves in two separate lists
while number > 1: #We will divide the number until it is less than zero, which means there are no more digits
rem = number % 10
not_every_other_digit.append(rem)
number /= 10
number = math.floor(number)
rem = number % 10
every_other_digit.append(rem)
number /= 10
number = math.floor(number)
#In this for loop we iterate through the digits in every_other_digits and appends those
#digits multiplied by two to a new list
for digit in every_other_digit:
every_other_digit_times_two.append(digit * 2)
#Because we are supposed to add only the digits of the products of every other digit times two, we must create
#two conditionals. The first if- statement is for digits from 0-9. The else- statement is for numbers > 10,
#where we must first split the number into two digits and then sum those digits to sum_of_digits_every_other_digit_times_two
for digit in every_other_digit_times_two:
if digit < 10:
sum_of_digits_in_every_other_digit += digit
else:
second_digit = digit % 10
first_digit = math.floor(digit / 10)
sum_of_digits_in_every_other_digit += first_digit
sum_of_digits_in_every_other_digit += second_digit
#Creates empty counter so that we can add the digits not multiplied by two
sum_of_digits_not_multiplied_by_two = 0
#Iterates through digits in the half that is not multiplied by two, and adds them to counter
for digit in not_every_other_digit:
sum_of_digits_not_multiplied_by_two += digit
#Finally we can get the target sum, which is the sum of the two counters we have made above
target_sum = sum_of_digits_in_every_other_digit + sum_of_digits_not_multiplied_by_two
#If last digit of target sum is 0, the credit card number is legit
if target_sum % 10 == 0:
valid = True
return valid
#In this function we will determine which company has issued the credit card, and use our function luhns_algorithm to
#check if the credit card number is valid
def credit_card(num):
digits = 0
company = ""
number = num
valid = luhns_algorithm(num)
if valid == True:
while number > 1:
digits += 1
number /= 10
first_two_digits = num / 10 ** (digits - 2)
first_two_digits = math.floor(first_two_digits)
first_digit = first_two_digits / 10
if digits == 15:
if first_two_digits == 34 or first_two_digits == 37:
company = "AMEX"
elif digits == 13:
company = "VISA"
elif digits == 16 and first_digit == 4:
company = "VISA"
elif digits == 16 and 51 <= first_two_digits <= 55:
company = "MasterCard"
else:
return print("The credit card number is invalid.")
return print("The credit card is issued by " + company)
credit_card(4003600000000014)
#Output = The credit card is issued by VISA
\$\begingroup\$
\$\endgroup\$
1
-
\$\begingroup\$ There is a lot of redundant comments and blank lines. I would start there. \$\endgroup\$– slepicCommented Feb 16, 2021 at 12:41
Add a comment
|
1 Answer
\$\begingroup\$
\$\endgroup\$
There's a tonne of intermediate variables that don't need to exist, as well as insisting that the credit card number be treated as an integer when a string is probably easier.
Also, don't bake printing into your functions, and don't require that the company determination logic operate on a valid card. Add type hints, and this brings you to
from typing import Optional
def is_card_valid(num: str) -> bool:
if not num.isdigit():
return False
total = sum(
int(num[i])
for i in range(1, len(num), 2)
)
for i in range(0, len(num), 2):
d1, d2 = divmod(2*int(num[i]), 10)
total += d1 + d2
return total % 10 == 0
def get_card_company(num: str) -> Optional[str]:
digits = len(num)
if digits == 15:
if num[:2] in {'34', '37'}:
return 'AMEX'
if num[:2] == '13':
return 'VISA'
elif digits == 16:
if num[0] == '4':
return 'VISA'
if num[0] == '5' and num[1] in '12345':
return 'MasterCard'
card = '4003600000000014'
if is_card_valid(card):
print('Card is valid')
print('The credit card is issued by', get_card_company(card))
else:
print('Card is invalid')