# How can I shorten this program using Luhn's algorithm to check credit card number?

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

• There is a lot of redundant comments and blank lines. I would start there. Feb 16, 2021 at 12:41

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

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')