2
\$\begingroup\$
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
\$\endgroup\$
1
  • \$\begingroup\$ There is a lot of redundant comments and blank lines. I would start there. \$\endgroup\$
    – slepic
    Commented Feb 16, 2021 at 12:41

1 Answer 1

1
\$\begingroup\$

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')
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.