Credit card validator using Luhn Algorithm





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







7












$begingroup$


I'm looking for feedback or tips to maybe make my code more readable or faster or just general tips to help get myself started with app making with Python.



import sys

# check for valid input
if len(sys.argv) == 2:
try:
int(sys.argv[1])
if(len(str(sys.argv[1])) == 16):
pass
else:
print("Not 16 digits!")
sys.exit()
except ValueError:
print('Not an integer!')
sys.exit()
else:
print('Not enough or too many command line arguments! n Proper use "python Check.py <credit card number here> " ')
sys.exit()

def main():
# put the digits into a list
number = convertToList(sys.argv[1])
sum = cardCheck(number)
if (sum%10 == 0):
print('Valid Card!')
else:
print('Invalid Card!')

#converts initial passed int variable to list
def convertToList(num):
numStr = str(num)
numList =
for digit in numStr:
numList.append(int(digit))
return (numList)

def cardCheck(digitList, count = 0):
sum = 0
#if digit is every second digit multiply by 2
if(count%2 == 0 & count < 15):
digitList[count] = (digitList[count] * 2)
#if is 2 digit number after multiplication
if(digitList[count] >= 10):
digitList[count] = addDigits(digitList[count])
cardCheck(digitList, count + 1)
else:
cardCheck(digitList, count + 1)
#progresses program
elif(count < 15):
cardCheck(digitList, count + 1)
else:
return 0
for digits in digitList:
sum += int(digits)
return sum

#resolve 2 digit number conflict by adding the digits of the number and returning it
def addDigits(num):
list = str(num)
sum = 0
for digits in list:
sum += int(digits)
return sum

if __name__ == '__main__':
main()









share|improve this question











$endgroup$










  • 2




    $begingroup$
    For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
    $endgroup$
    – jpmc26
    May 26 at 15:52












  • $begingroup$
    I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
    $endgroup$
    – tph
    May 26 at 16:23


















7












$begingroup$


I'm looking for feedback or tips to maybe make my code more readable or faster or just general tips to help get myself started with app making with Python.



import sys

# check for valid input
if len(sys.argv) == 2:
try:
int(sys.argv[1])
if(len(str(sys.argv[1])) == 16):
pass
else:
print("Not 16 digits!")
sys.exit()
except ValueError:
print('Not an integer!')
sys.exit()
else:
print('Not enough or too many command line arguments! n Proper use "python Check.py <credit card number here> " ')
sys.exit()

def main():
# put the digits into a list
number = convertToList(sys.argv[1])
sum = cardCheck(number)
if (sum%10 == 0):
print('Valid Card!')
else:
print('Invalid Card!')

#converts initial passed int variable to list
def convertToList(num):
numStr = str(num)
numList =
for digit in numStr:
numList.append(int(digit))
return (numList)

def cardCheck(digitList, count = 0):
sum = 0
#if digit is every second digit multiply by 2
if(count%2 == 0 & count < 15):
digitList[count] = (digitList[count] * 2)
#if is 2 digit number after multiplication
if(digitList[count] >= 10):
digitList[count] = addDigits(digitList[count])
cardCheck(digitList, count + 1)
else:
cardCheck(digitList, count + 1)
#progresses program
elif(count < 15):
cardCheck(digitList, count + 1)
else:
return 0
for digits in digitList:
sum += int(digits)
return sum

#resolve 2 digit number conflict by adding the digits of the number and returning it
def addDigits(num):
list = str(num)
sum = 0
for digits in list:
sum += int(digits)
return sum

if __name__ == '__main__':
main()









share|improve this question











$endgroup$










  • 2




    $begingroup$
    For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
    $endgroup$
    – jpmc26
    May 26 at 15:52












  • $begingroup$
    I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
    $endgroup$
    – tph
    May 26 at 16:23














7












7








7





$begingroup$


I'm looking for feedback or tips to maybe make my code more readable or faster or just general tips to help get myself started with app making with Python.



import sys

# check for valid input
if len(sys.argv) == 2:
try:
int(sys.argv[1])
if(len(str(sys.argv[1])) == 16):
pass
else:
print("Not 16 digits!")
sys.exit()
except ValueError:
print('Not an integer!')
sys.exit()
else:
print('Not enough or too many command line arguments! n Proper use "python Check.py <credit card number here> " ')
sys.exit()

def main():
# put the digits into a list
number = convertToList(sys.argv[1])
sum = cardCheck(number)
if (sum%10 == 0):
print('Valid Card!')
else:
print('Invalid Card!')

#converts initial passed int variable to list
def convertToList(num):
numStr = str(num)
numList =
for digit in numStr:
numList.append(int(digit))
return (numList)

def cardCheck(digitList, count = 0):
sum = 0
#if digit is every second digit multiply by 2
if(count%2 == 0 & count < 15):
digitList[count] = (digitList[count] * 2)
#if is 2 digit number after multiplication
if(digitList[count] >= 10):
digitList[count] = addDigits(digitList[count])
cardCheck(digitList, count + 1)
else:
cardCheck(digitList, count + 1)
#progresses program
elif(count < 15):
cardCheck(digitList, count + 1)
else:
return 0
for digits in digitList:
sum += int(digits)
return sum

#resolve 2 digit number conflict by adding the digits of the number and returning it
def addDigits(num):
list = str(num)
sum = 0
for digits in list:
sum += int(digits)
return sum

if __name__ == '__main__':
main()









share|improve this question











$endgroup$




I'm looking for feedback or tips to maybe make my code more readable or faster or just general tips to help get myself started with app making with Python.



import sys

# check for valid input
if len(sys.argv) == 2:
try:
int(sys.argv[1])
if(len(str(sys.argv[1])) == 16):
pass
else:
print("Not 16 digits!")
sys.exit()
except ValueError:
print('Not an integer!')
sys.exit()
else:
print('Not enough or too many command line arguments! n Proper use "python Check.py <credit card number here> " ')
sys.exit()

def main():
# put the digits into a list
number = convertToList(sys.argv[1])
sum = cardCheck(number)
if (sum%10 == 0):
print('Valid Card!')
else:
print('Invalid Card!')

#converts initial passed int variable to list
def convertToList(num):
numStr = str(num)
numList =
for digit in numStr:
numList.append(int(digit))
return (numList)

def cardCheck(digitList, count = 0):
sum = 0
#if digit is every second digit multiply by 2
if(count%2 == 0 & count < 15):
digitList[count] = (digitList[count] * 2)
#if is 2 digit number after multiplication
if(digitList[count] >= 10):
digitList[count] = addDigits(digitList[count])
cardCheck(digitList, count + 1)
else:
cardCheck(digitList, count + 1)
#progresses program
elif(count < 15):
cardCheck(digitList, count + 1)
else:
return 0
for digits in digitList:
sum += int(digits)
return sum

#resolve 2 digit number conflict by adding the digits of the number and returning it
def addDigits(num):
list = str(num)
sum = 0
for digits in list:
sum += int(digits)
return sum

if __name__ == '__main__':
main()






python beginner checksum






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 26 at 3:23









200_success

135k21 gold badges173 silver badges443 bronze badges




135k21 gold badges173 silver badges443 bronze badges










asked May 26 at 3:16









tphtph

384 bronze badges




384 bronze badges











  • 2




    $begingroup$
    For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
    $endgroup$
    – jpmc26
    May 26 at 15:52












  • $begingroup$
    I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
    $endgroup$
    – tph
    May 26 at 16:23














  • 2




    $begingroup$
    For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
    $endgroup$
    – jpmc26
    May 26 at 15:52












  • $begingroup$
    I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
    $endgroup$
    – tph
    May 26 at 16:23








2




2




$begingroup$
For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
$endgroup$
– jpmc26
May 26 at 15:52






$begingroup$
For the record, if you're just getting started making apps, credit card handling is not the best place, given the immense legal/contractual requirements/standards around them. Most businesses will want to outsource card handling.
$endgroup$
– jpmc26
May 26 at 15:52














$begingroup$
I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
$endgroup$
– tph
May 26 at 16:23




$begingroup$
I understand that, I was simply testing my abilities to write a simple checksum algorithm. I plan on writing a program to solve Rubix cubes soon as my first big project.
$endgroup$
– tph
May 26 at 16:23










2 Answers
2






active

oldest

votes


















8












$begingroup$

For making your code faster, we can choose more Pythonic ways in some parts of it.
First, let's take a look at convertToList function. The goal of this function is to split digits of a number to a list of int values. I want to follow your algorithm and do this by converting the number to the str and then splitting it.



I want to do this by "List Comprehension":



def convert_to_list(num):
result = [int(x) for x in str(num)]
return result


We made some changes here. First of all, I changed the name of the function from camelCase (convertToList) to snake_case (convert_to_list) because according to the Python style guide, it is the better way. You can read more about the Python style guide at PEP8.



Next change is I replaced all your code with a single line list comprehension. The first advantage, we have written less code. Less code means probably fewer bugs.



But the second advantage here is this code is so much faster. How much? I have written a simple script for it; the result is that on average, the second version is 1.7 times faster.



Now let's move on and take another look at addDigits function. I want to choose pythonic way again here:



def sum_of_digits(number):
num_list = convert_to_list(number)
return sum(num_list)


Like the previous time, I changed the name. I think this name is clearer and everyone could tell what this code does.



For converting the number to a list of digits, I used convert_to_list function instead of writing the whole code again. We are using functions to avoiding duplication, so I think it's a bad idea to write the same code here. For calculating the sum of digits in a list, I strongly recommend you that always use built-in function sum. It's faster, you don't need to write new code and every Python programmer can tell what you are doing at first glance. This code is somehow 1.2 times faster than previous.



Now let's go to the beginning of your code. We want to parse command line parameters and be sure that the input is correct.



Even though we only call those codes once, I think it is a great favor to the readability of the code to move those lines in a separate function.



from re import search


def get_input_from_cmd(args_list):
if len(args_list) != 2:
raise Exception("You should enter a 16-digit number as input argument")
return args_list[1]


def is_input_valid(input_str):
return bool(search(r"d{16}", input_str))


I separated your code into two functions. The first function gets argv list as an input parameter and if its length is equal to 2, returns the second parameter. Else, it will raise an Exception. There are a lot of people out there who are against exceptions and I agree with most of their reasons. But when we want our program to stop when a bad input came in, I think using exceptions is the best way.



The second function simply uss search function of re module. It checks that the input string only contains 16 digits. If that assumption will be true, True will be returned. Otherwise, the False value is what you get.



Now you can change your main function like this:



def main():
input_string = get_input_from_cmd(sys.argv)
if is_input_valid(input_string):
digits_list = convert_to_list(input_string)
card_checking_sum = card_check(digits_list)
if card_checking_sum % 10 == 0:
print('Valid Card!')
else:
print('Invalid Card!')
else:
print("Invalid Card number")


What we do is if card number is not a 16-digit number, code in the last else will execute. Otherwise, codes in the first if will run. That looks nicer to me.



So now let's go to the last function, the cardCheck.



def card_check(digits_list, count=0):
result = 0
if count % 2 == 0:
digits_list[count] *= 2
if digits_list[count] >= 10:
digits_list[count] = sum_of_digits(digits_list[count])
if count < 15:
card_check(digits_list, count + 1)
else:
return 0
result += sum(digits_list)
return result


There were some problems in your code that I tried to fix. First, you don't need to put if conditions in parentheses. In python, don't need means you should not.



Second, if you run the same code in if and else; you should take that part of code away from if statement. That is what I did with card_check(digits_list, count + 1) line. That line was repeated needlessly.



In the end, for logical operations, you should use operators like and and or, not & and |.



Here is the full code. I hope that helps you:



from re import search
import sys


def get_input_from_cmd(args_list):
if len(args_list) != 2:
raise Exception("You should enter a 16-digit number as input argument")
return args_list[1]


def is_input_valid(input_str):
return bool(search(r"d{16}", input_str))


def convert_to_list(num):
result = [int(x) for x in str(num)]
return result


def sum_of_digits(number):
num_list = convert_to_list(number)
return sum(num_list)


def card_check(digits_list, count=0):
result = 0
if count % 2 == 0:
digits_list[count] *= 2
if digits_list[count] >= 10:
digits_list[count] = sum_of_digits(digits_list[count])
if count < 15:
card_check(digits_list, count + 1)
else:
return 0
result += sum(digits_list)
return result


def main():
input_string = get_input_from_cmd(sys.argv)
if is_input_valid(input_string):
digits_list = convert_to_list(input_string)
card_checking_sum = card_check(digits_list)
if card_checking_sum % 10 == 0:
print('Valid Card!')
else:
print('Invalid Card!')
else:
print("Invalid Card number")


if __name__ == '__main__':
main()





share|improve this answer











$endgroup$























    7












    $begingroup$

    Regarding the cardCheck function: Its main purpose is to help you determine if a card number is valid, using the Luhn algorithm. So why have it return a sum, rather than a True or False? I can't imagine a scenario where you'd want to call that function and NOT want to do the sum % 10 == 0 check after. So include that in the function, that seems to be a core part of its job. The main function can then be more explicit when using it:



    valid = cardCheck(number):
    if valid:
    print('Valid card!')


    Also, there's no reason to make this function recursive. That seems to only make it harder to understand. Compare with this variant that iterates over the digits instead:



    def cardCheck(digit_list):
    if len(digit_list) != 16:
    return False
    total = 0
    for i, digit in enumerate(digit_list):
    if i % 2 == 0:
    digit *= 2
    if digit >= 10:
    digit -= 9
    total += digit
    return total % 10 == 0


    I used a trick here to replace the digit sum: If the digit sum is needed, that will be on a number between 10 and 18. The digit sum of those numbers is just 1 above the last digit, and that number can be more easily found by just subtracting 9. But whether you use that trick or not, the iterative version seems easier to understand and read.






    share|improve this answer









    $endgroup$


















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "196"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f221030%2fcredit-card-validator-using-luhn-algorithm%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      8












      $begingroup$

      For making your code faster, we can choose more Pythonic ways in some parts of it.
      First, let's take a look at convertToList function. The goal of this function is to split digits of a number to a list of int values. I want to follow your algorithm and do this by converting the number to the str and then splitting it.



      I want to do this by "List Comprehension":



      def convert_to_list(num):
      result = [int(x) for x in str(num)]
      return result


      We made some changes here. First of all, I changed the name of the function from camelCase (convertToList) to snake_case (convert_to_list) because according to the Python style guide, it is the better way. You can read more about the Python style guide at PEP8.



      Next change is I replaced all your code with a single line list comprehension. The first advantage, we have written less code. Less code means probably fewer bugs.



      But the second advantage here is this code is so much faster. How much? I have written a simple script for it; the result is that on average, the second version is 1.7 times faster.



      Now let's move on and take another look at addDigits function. I want to choose pythonic way again here:



      def sum_of_digits(number):
      num_list = convert_to_list(number)
      return sum(num_list)


      Like the previous time, I changed the name. I think this name is clearer and everyone could tell what this code does.



      For converting the number to a list of digits, I used convert_to_list function instead of writing the whole code again. We are using functions to avoiding duplication, so I think it's a bad idea to write the same code here. For calculating the sum of digits in a list, I strongly recommend you that always use built-in function sum. It's faster, you don't need to write new code and every Python programmer can tell what you are doing at first glance. This code is somehow 1.2 times faster than previous.



      Now let's go to the beginning of your code. We want to parse command line parameters and be sure that the input is correct.



      Even though we only call those codes once, I think it is a great favor to the readability of the code to move those lines in a separate function.



      from re import search


      def get_input_from_cmd(args_list):
      if len(args_list) != 2:
      raise Exception("You should enter a 16-digit number as input argument")
      return args_list[1]


      def is_input_valid(input_str):
      return bool(search(r"d{16}", input_str))


      I separated your code into two functions. The first function gets argv list as an input parameter and if its length is equal to 2, returns the second parameter. Else, it will raise an Exception. There are a lot of people out there who are against exceptions and I agree with most of their reasons. But when we want our program to stop when a bad input came in, I think using exceptions is the best way.



      The second function simply uss search function of re module. It checks that the input string only contains 16 digits. If that assumption will be true, True will be returned. Otherwise, the False value is what you get.



      Now you can change your main function like this:



      def main():
      input_string = get_input_from_cmd(sys.argv)
      if is_input_valid(input_string):
      digits_list = convert_to_list(input_string)
      card_checking_sum = card_check(digits_list)
      if card_checking_sum % 10 == 0:
      print('Valid Card!')
      else:
      print('Invalid Card!')
      else:
      print("Invalid Card number")


      What we do is if card number is not a 16-digit number, code in the last else will execute. Otherwise, codes in the first if will run. That looks nicer to me.



      So now let's go to the last function, the cardCheck.



      def card_check(digits_list, count=0):
      result = 0
      if count % 2 == 0:
      digits_list[count] *= 2
      if digits_list[count] >= 10:
      digits_list[count] = sum_of_digits(digits_list[count])
      if count < 15:
      card_check(digits_list, count + 1)
      else:
      return 0
      result += sum(digits_list)
      return result


      There were some problems in your code that I tried to fix. First, you don't need to put if conditions in parentheses. In python, don't need means you should not.



      Second, if you run the same code in if and else; you should take that part of code away from if statement. That is what I did with card_check(digits_list, count + 1) line. That line was repeated needlessly.



      In the end, for logical operations, you should use operators like and and or, not & and |.



      Here is the full code. I hope that helps you:



      from re import search
      import sys


      def get_input_from_cmd(args_list):
      if len(args_list) != 2:
      raise Exception("You should enter a 16-digit number as input argument")
      return args_list[1]


      def is_input_valid(input_str):
      return bool(search(r"d{16}", input_str))


      def convert_to_list(num):
      result = [int(x) for x in str(num)]
      return result


      def sum_of_digits(number):
      num_list = convert_to_list(number)
      return sum(num_list)


      def card_check(digits_list, count=0):
      result = 0
      if count % 2 == 0:
      digits_list[count] *= 2
      if digits_list[count] >= 10:
      digits_list[count] = sum_of_digits(digits_list[count])
      if count < 15:
      card_check(digits_list, count + 1)
      else:
      return 0
      result += sum(digits_list)
      return result


      def main():
      input_string = get_input_from_cmd(sys.argv)
      if is_input_valid(input_string):
      digits_list = convert_to_list(input_string)
      card_checking_sum = card_check(digits_list)
      if card_checking_sum % 10 == 0:
      print('Valid Card!')
      else:
      print('Invalid Card!')
      else:
      print("Invalid Card number")


      if __name__ == '__main__':
      main()





      share|improve this answer











      $endgroup$




















        8












        $begingroup$

        For making your code faster, we can choose more Pythonic ways in some parts of it.
        First, let's take a look at convertToList function. The goal of this function is to split digits of a number to a list of int values. I want to follow your algorithm and do this by converting the number to the str and then splitting it.



        I want to do this by "List Comprehension":



        def convert_to_list(num):
        result = [int(x) for x in str(num)]
        return result


        We made some changes here. First of all, I changed the name of the function from camelCase (convertToList) to snake_case (convert_to_list) because according to the Python style guide, it is the better way. You can read more about the Python style guide at PEP8.



        Next change is I replaced all your code with a single line list comprehension. The first advantage, we have written less code. Less code means probably fewer bugs.



        But the second advantage here is this code is so much faster. How much? I have written a simple script for it; the result is that on average, the second version is 1.7 times faster.



        Now let's move on and take another look at addDigits function. I want to choose pythonic way again here:



        def sum_of_digits(number):
        num_list = convert_to_list(number)
        return sum(num_list)


        Like the previous time, I changed the name. I think this name is clearer and everyone could tell what this code does.



        For converting the number to a list of digits, I used convert_to_list function instead of writing the whole code again. We are using functions to avoiding duplication, so I think it's a bad idea to write the same code here. For calculating the sum of digits in a list, I strongly recommend you that always use built-in function sum. It's faster, you don't need to write new code and every Python programmer can tell what you are doing at first glance. This code is somehow 1.2 times faster than previous.



        Now let's go to the beginning of your code. We want to parse command line parameters and be sure that the input is correct.



        Even though we only call those codes once, I think it is a great favor to the readability of the code to move those lines in a separate function.



        from re import search


        def get_input_from_cmd(args_list):
        if len(args_list) != 2:
        raise Exception("You should enter a 16-digit number as input argument")
        return args_list[1]


        def is_input_valid(input_str):
        return bool(search(r"d{16}", input_str))


        I separated your code into two functions. The first function gets argv list as an input parameter and if its length is equal to 2, returns the second parameter. Else, it will raise an Exception. There are a lot of people out there who are against exceptions and I agree with most of their reasons. But when we want our program to stop when a bad input came in, I think using exceptions is the best way.



        The second function simply uss search function of re module. It checks that the input string only contains 16 digits. If that assumption will be true, True will be returned. Otherwise, the False value is what you get.



        Now you can change your main function like this:



        def main():
        input_string = get_input_from_cmd(sys.argv)
        if is_input_valid(input_string):
        digits_list = convert_to_list(input_string)
        card_checking_sum = card_check(digits_list)
        if card_checking_sum % 10 == 0:
        print('Valid Card!')
        else:
        print('Invalid Card!')
        else:
        print("Invalid Card number")


        What we do is if card number is not a 16-digit number, code in the last else will execute. Otherwise, codes in the first if will run. That looks nicer to me.



        So now let's go to the last function, the cardCheck.



        def card_check(digits_list, count=0):
        result = 0
        if count % 2 == 0:
        digits_list[count] *= 2
        if digits_list[count] >= 10:
        digits_list[count] = sum_of_digits(digits_list[count])
        if count < 15:
        card_check(digits_list, count + 1)
        else:
        return 0
        result += sum(digits_list)
        return result


        There were some problems in your code that I tried to fix. First, you don't need to put if conditions in parentheses. In python, don't need means you should not.



        Second, if you run the same code in if and else; you should take that part of code away from if statement. That is what I did with card_check(digits_list, count + 1) line. That line was repeated needlessly.



        In the end, for logical operations, you should use operators like and and or, not & and |.



        Here is the full code. I hope that helps you:



        from re import search
        import sys


        def get_input_from_cmd(args_list):
        if len(args_list) != 2:
        raise Exception("You should enter a 16-digit number as input argument")
        return args_list[1]


        def is_input_valid(input_str):
        return bool(search(r"d{16}", input_str))


        def convert_to_list(num):
        result = [int(x) for x in str(num)]
        return result


        def sum_of_digits(number):
        num_list = convert_to_list(number)
        return sum(num_list)


        def card_check(digits_list, count=0):
        result = 0
        if count % 2 == 0:
        digits_list[count] *= 2
        if digits_list[count] >= 10:
        digits_list[count] = sum_of_digits(digits_list[count])
        if count < 15:
        card_check(digits_list, count + 1)
        else:
        return 0
        result += sum(digits_list)
        return result


        def main():
        input_string = get_input_from_cmd(sys.argv)
        if is_input_valid(input_string):
        digits_list = convert_to_list(input_string)
        card_checking_sum = card_check(digits_list)
        if card_checking_sum % 10 == 0:
        print('Valid Card!')
        else:
        print('Invalid Card!')
        else:
        print("Invalid Card number")


        if __name__ == '__main__':
        main()





        share|improve this answer











        $endgroup$


















          8












          8








          8





          $begingroup$

          For making your code faster, we can choose more Pythonic ways in some parts of it.
          First, let's take a look at convertToList function. The goal of this function is to split digits of a number to a list of int values. I want to follow your algorithm and do this by converting the number to the str and then splitting it.



          I want to do this by "List Comprehension":



          def convert_to_list(num):
          result = [int(x) for x in str(num)]
          return result


          We made some changes here. First of all, I changed the name of the function from camelCase (convertToList) to snake_case (convert_to_list) because according to the Python style guide, it is the better way. You can read more about the Python style guide at PEP8.



          Next change is I replaced all your code with a single line list comprehension. The first advantage, we have written less code. Less code means probably fewer bugs.



          But the second advantage here is this code is so much faster. How much? I have written a simple script for it; the result is that on average, the second version is 1.7 times faster.



          Now let's move on and take another look at addDigits function. I want to choose pythonic way again here:



          def sum_of_digits(number):
          num_list = convert_to_list(number)
          return sum(num_list)


          Like the previous time, I changed the name. I think this name is clearer and everyone could tell what this code does.



          For converting the number to a list of digits, I used convert_to_list function instead of writing the whole code again. We are using functions to avoiding duplication, so I think it's a bad idea to write the same code here. For calculating the sum of digits in a list, I strongly recommend you that always use built-in function sum. It's faster, you don't need to write new code and every Python programmer can tell what you are doing at first glance. This code is somehow 1.2 times faster than previous.



          Now let's go to the beginning of your code. We want to parse command line parameters and be sure that the input is correct.



          Even though we only call those codes once, I think it is a great favor to the readability of the code to move those lines in a separate function.



          from re import search


          def get_input_from_cmd(args_list):
          if len(args_list) != 2:
          raise Exception("You should enter a 16-digit number as input argument")
          return args_list[1]


          def is_input_valid(input_str):
          return bool(search(r"d{16}", input_str))


          I separated your code into two functions. The first function gets argv list as an input parameter and if its length is equal to 2, returns the second parameter. Else, it will raise an Exception. There are a lot of people out there who are against exceptions and I agree with most of their reasons. But when we want our program to stop when a bad input came in, I think using exceptions is the best way.



          The second function simply uss search function of re module. It checks that the input string only contains 16 digits. If that assumption will be true, True will be returned. Otherwise, the False value is what you get.



          Now you can change your main function like this:



          def main():
          input_string = get_input_from_cmd(sys.argv)
          if is_input_valid(input_string):
          digits_list = convert_to_list(input_string)
          card_checking_sum = card_check(digits_list)
          if card_checking_sum % 10 == 0:
          print('Valid Card!')
          else:
          print('Invalid Card!')
          else:
          print("Invalid Card number")


          What we do is if card number is not a 16-digit number, code in the last else will execute. Otherwise, codes in the first if will run. That looks nicer to me.



          So now let's go to the last function, the cardCheck.



          def card_check(digits_list, count=0):
          result = 0
          if count % 2 == 0:
          digits_list[count] *= 2
          if digits_list[count] >= 10:
          digits_list[count] = sum_of_digits(digits_list[count])
          if count < 15:
          card_check(digits_list, count + 1)
          else:
          return 0
          result += sum(digits_list)
          return result


          There were some problems in your code that I tried to fix. First, you don't need to put if conditions in parentheses. In python, don't need means you should not.



          Second, if you run the same code in if and else; you should take that part of code away from if statement. That is what I did with card_check(digits_list, count + 1) line. That line was repeated needlessly.



          In the end, for logical operations, you should use operators like and and or, not & and |.



          Here is the full code. I hope that helps you:



          from re import search
          import sys


          def get_input_from_cmd(args_list):
          if len(args_list) != 2:
          raise Exception("You should enter a 16-digit number as input argument")
          return args_list[1]


          def is_input_valid(input_str):
          return bool(search(r"d{16}", input_str))


          def convert_to_list(num):
          result = [int(x) for x in str(num)]
          return result


          def sum_of_digits(number):
          num_list = convert_to_list(number)
          return sum(num_list)


          def card_check(digits_list, count=0):
          result = 0
          if count % 2 == 0:
          digits_list[count] *= 2
          if digits_list[count] >= 10:
          digits_list[count] = sum_of_digits(digits_list[count])
          if count < 15:
          card_check(digits_list, count + 1)
          else:
          return 0
          result += sum(digits_list)
          return result


          def main():
          input_string = get_input_from_cmd(sys.argv)
          if is_input_valid(input_string):
          digits_list = convert_to_list(input_string)
          card_checking_sum = card_check(digits_list)
          if card_checking_sum % 10 == 0:
          print('Valid Card!')
          else:
          print('Invalid Card!')
          else:
          print("Invalid Card number")


          if __name__ == '__main__':
          main()





          share|improve this answer











          $endgroup$



          For making your code faster, we can choose more Pythonic ways in some parts of it.
          First, let's take a look at convertToList function. The goal of this function is to split digits of a number to a list of int values. I want to follow your algorithm and do this by converting the number to the str and then splitting it.



          I want to do this by "List Comprehension":



          def convert_to_list(num):
          result = [int(x) for x in str(num)]
          return result


          We made some changes here. First of all, I changed the name of the function from camelCase (convertToList) to snake_case (convert_to_list) because according to the Python style guide, it is the better way. You can read more about the Python style guide at PEP8.



          Next change is I replaced all your code with a single line list comprehension. The first advantage, we have written less code. Less code means probably fewer bugs.



          But the second advantage here is this code is so much faster. How much? I have written a simple script for it; the result is that on average, the second version is 1.7 times faster.



          Now let's move on and take another look at addDigits function. I want to choose pythonic way again here:



          def sum_of_digits(number):
          num_list = convert_to_list(number)
          return sum(num_list)


          Like the previous time, I changed the name. I think this name is clearer and everyone could tell what this code does.



          For converting the number to a list of digits, I used convert_to_list function instead of writing the whole code again. We are using functions to avoiding duplication, so I think it's a bad idea to write the same code here. For calculating the sum of digits in a list, I strongly recommend you that always use built-in function sum. It's faster, you don't need to write new code and every Python programmer can tell what you are doing at first glance. This code is somehow 1.2 times faster than previous.



          Now let's go to the beginning of your code. We want to parse command line parameters and be sure that the input is correct.



          Even though we only call those codes once, I think it is a great favor to the readability of the code to move those lines in a separate function.



          from re import search


          def get_input_from_cmd(args_list):
          if len(args_list) != 2:
          raise Exception("You should enter a 16-digit number as input argument")
          return args_list[1]


          def is_input_valid(input_str):
          return bool(search(r"d{16}", input_str))


          I separated your code into two functions. The first function gets argv list as an input parameter and if its length is equal to 2, returns the second parameter. Else, it will raise an Exception. There are a lot of people out there who are against exceptions and I agree with most of their reasons. But when we want our program to stop when a bad input came in, I think using exceptions is the best way.



          The second function simply uss search function of re module. It checks that the input string only contains 16 digits. If that assumption will be true, True will be returned. Otherwise, the False value is what you get.



          Now you can change your main function like this:



          def main():
          input_string = get_input_from_cmd(sys.argv)
          if is_input_valid(input_string):
          digits_list = convert_to_list(input_string)
          card_checking_sum = card_check(digits_list)
          if card_checking_sum % 10 == 0:
          print('Valid Card!')
          else:
          print('Invalid Card!')
          else:
          print("Invalid Card number")


          What we do is if card number is not a 16-digit number, code in the last else will execute. Otherwise, codes in the first if will run. That looks nicer to me.



          So now let's go to the last function, the cardCheck.



          def card_check(digits_list, count=0):
          result = 0
          if count % 2 == 0:
          digits_list[count] *= 2
          if digits_list[count] >= 10:
          digits_list[count] = sum_of_digits(digits_list[count])
          if count < 15:
          card_check(digits_list, count + 1)
          else:
          return 0
          result += sum(digits_list)
          return result


          There were some problems in your code that I tried to fix. First, you don't need to put if conditions in parentheses. In python, don't need means you should not.



          Second, if you run the same code in if and else; you should take that part of code away from if statement. That is what I did with card_check(digits_list, count + 1) line. That line was repeated needlessly.



          In the end, for logical operations, you should use operators like and and or, not & and |.



          Here is the full code. I hope that helps you:



          from re import search
          import sys


          def get_input_from_cmd(args_list):
          if len(args_list) != 2:
          raise Exception("You should enter a 16-digit number as input argument")
          return args_list[1]


          def is_input_valid(input_str):
          return bool(search(r"d{16}", input_str))


          def convert_to_list(num):
          result = [int(x) for x in str(num)]
          return result


          def sum_of_digits(number):
          num_list = convert_to_list(number)
          return sum(num_list)


          def card_check(digits_list, count=0):
          result = 0
          if count % 2 == 0:
          digits_list[count] *= 2
          if digits_list[count] >= 10:
          digits_list[count] = sum_of_digits(digits_list[count])
          if count < 15:
          card_check(digits_list, count + 1)
          else:
          return 0
          result += sum(digits_list)
          return result


          def main():
          input_string = get_input_from_cmd(sys.argv)
          if is_input_valid(input_string):
          digits_list = convert_to_list(input_string)
          card_checking_sum = card_check(digits_list)
          if card_checking_sum % 10 == 0:
          print('Valid Card!')
          else:
          print('Invalid Card!')
          else:
          print("Invalid Card number")


          if __name__ == '__main__':
          main()






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited May 30 at 11:49









          Toby Speight

          31.1k7 gold badges45 silver badges135 bronze badges




          31.1k7 gold badges45 silver badges135 bronze badges










          answered May 26 at 6:26









          Mr AlihoseinyMr Alihoseiny

          3548 bronze badges




          3548 bronze badges




























              7












              $begingroup$

              Regarding the cardCheck function: Its main purpose is to help you determine if a card number is valid, using the Luhn algorithm. So why have it return a sum, rather than a True or False? I can't imagine a scenario where you'd want to call that function and NOT want to do the sum % 10 == 0 check after. So include that in the function, that seems to be a core part of its job. The main function can then be more explicit when using it:



              valid = cardCheck(number):
              if valid:
              print('Valid card!')


              Also, there's no reason to make this function recursive. That seems to only make it harder to understand. Compare with this variant that iterates over the digits instead:



              def cardCheck(digit_list):
              if len(digit_list) != 16:
              return False
              total = 0
              for i, digit in enumerate(digit_list):
              if i % 2 == 0:
              digit *= 2
              if digit >= 10:
              digit -= 9
              total += digit
              return total % 10 == 0


              I used a trick here to replace the digit sum: If the digit sum is needed, that will be on a number between 10 and 18. The digit sum of those numbers is just 1 above the last digit, and that number can be more easily found by just subtracting 9. But whether you use that trick or not, the iterative version seems easier to understand and read.






              share|improve this answer









              $endgroup$




















                7












                $begingroup$

                Regarding the cardCheck function: Its main purpose is to help you determine if a card number is valid, using the Luhn algorithm. So why have it return a sum, rather than a True or False? I can't imagine a scenario where you'd want to call that function and NOT want to do the sum % 10 == 0 check after. So include that in the function, that seems to be a core part of its job. The main function can then be more explicit when using it:



                valid = cardCheck(number):
                if valid:
                print('Valid card!')


                Also, there's no reason to make this function recursive. That seems to only make it harder to understand. Compare with this variant that iterates over the digits instead:



                def cardCheck(digit_list):
                if len(digit_list) != 16:
                return False
                total = 0
                for i, digit in enumerate(digit_list):
                if i % 2 == 0:
                digit *= 2
                if digit >= 10:
                digit -= 9
                total += digit
                return total % 10 == 0


                I used a trick here to replace the digit sum: If the digit sum is needed, that will be on a number between 10 and 18. The digit sum of those numbers is just 1 above the last digit, and that number can be more easily found by just subtracting 9. But whether you use that trick or not, the iterative version seems easier to understand and read.






                share|improve this answer









                $endgroup$


















                  7












                  7








                  7





                  $begingroup$

                  Regarding the cardCheck function: Its main purpose is to help you determine if a card number is valid, using the Luhn algorithm. So why have it return a sum, rather than a True or False? I can't imagine a scenario where you'd want to call that function and NOT want to do the sum % 10 == 0 check after. So include that in the function, that seems to be a core part of its job. The main function can then be more explicit when using it:



                  valid = cardCheck(number):
                  if valid:
                  print('Valid card!')


                  Also, there's no reason to make this function recursive. That seems to only make it harder to understand. Compare with this variant that iterates over the digits instead:



                  def cardCheck(digit_list):
                  if len(digit_list) != 16:
                  return False
                  total = 0
                  for i, digit in enumerate(digit_list):
                  if i % 2 == 0:
                  digit *= 2
                  if digit >= 10:
                  digit -= 9
                  total += digit
                  return total % 10 == 0


                  I used a trick here to replace the digit sum: If the digit sum is needed, that will be on a number between 10 and 18. The digit sum of those numbers is just 1 above the last digit, and that number can be more easily found by just subtracting 9. But whether you use that trick or not, the iterative version seems easier to understand and read.






                  share|improve this answer









                  $endgroup$



                  Regarding the cardCheck function: Its main purpose is to help you determine if a card number is valid, using the Luhn algorithm. So why have it return a sum, rather than a True or False? I can't imagine a scenario where you'd want to call that function and NOT want to do the sum % 10 == 0 check after. So include that in the function, that seems to be a core part of its job. The main function can then be more explicit when using it:



                  valid = cardCheck(number):
                  if valid:
                  print('Valid card!')


                  Also, there's no reason to make this function recursive. That seems to only make it harder to understand. Compare with this variant that iterates over the digits instead:



                  def cardCheck(digit_list):
                  if len(digit_list) != 16:
                  return False
                  total = 0
                  for i, digit in enumerate(digit_list):
                  if i % 2 == 0:
                  digit *= 2
                  if digit >= 10:
                  digit -= 9
                  total += digit
                  return total % 10 == 0


                  I used a trick here to replace the digit sum: If the digit sum is needed, that will be on a number between 10 and 18. The digit sum of those numbers is just 1 above the last digit, and that number can be more easily found by just subtracting 9. But whether you use that trick or not, the iterative version seems easier to understand and read.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered May 26 at 7:51









                  SedsarqSedsarq

                  3496 bronze badges




                  3496 bronze badges

































                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f221030%2fcredit-card-validator-using-luhn-algorithm%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Færeyskur hestur Heimild | Tengill | Tilvísanir | LeiðsagnarvalRossið - síða um færeyska hrossið á færeyskuGott ár hjá færeyska hestinum

                      He _____ here since 1970 . Answer needed [closed]What does “since he was so high” mean?Meaning of “catch birds for”?How do I ensure “since” takes the meaning I want?“Who cares here” meaningWhat does “right round toward” mean?the time tense (had now been detected)What does the phrase “ring around the roses” mean here?Correct usage of “visited upon”Meaning of “foiled rail sabotage bid”It was the third time I had gone to Rome or It is the third time I had been to Rome

                      Slayer Innehåll Historia | Stil, komposition och lyrik | Bandets betydelse och framgångar | Sidoprojekt och samarbeten | Kontroverser | Medlemmar | Utmärkelser och nomineringar | Turnéer och festivaler | Diskografi | Referenser | Externa länkar | Navigeringsmenywww.slayer.net”Metal Massacre vol. 1””Metal Massacre vol. 3””Metal Massacre Volume III””Show No Mercy””Haunting the Chapel””Live Undead””Hell Awaits””Reign in Blood””Reign in Blood””Gold & Platinum – Reign in Blood””Golden Gods Awards Winners”originalet”Kerrang! Hall Of Fame””Slayer Looks Back On 37-Year Career In New Video Series: Part Two””South of Heaven””Gold & Platinum – South of Heaven””Seasons in the Abyss””Gold & Platinum - Seasons in the Abyss””Divine Intervention””Divine Intervention - Release group by Slayer””Gold & Platinum - Divine Intervention””Live Intrusion””Undisputed Attitude””Abolish Government/Superficial Love””Release “Slatanic Slaughter: A Tribute to Slayer” by Various Artists””Diabolus in Musica””Soundtrack to the Apocalypse””God Hates Us All””Systematic - Relationships””War at the Warfield””Gold & Platinum - War at the Warfield””Soundtrack to the Apocalypse””Gold & Platinum - Still Reigning””Metallica, Slayer, Iron Mauden Among Winners At Metal Hammer Awards””Eternal Pyre””Eternal Pyre - Slayer release group””Eternal Pyre””Metal Storm Awards 2006””Kerrang! Hall Of Fame””Slayer Wins 'Best Metal' Grammy Award””Slayer Guitarist Jeff Hanneman Dies””Bullet-For My Valentine booed at Metal Hammer Golden Gods Awards””Unholy Aliance””The End Of Slayer?””Slayer: We Could Thrash Out Two More Albums If We're Fast Enough...””'The Unholy Alliance: Chapter III' UK Dates Added”originalet”Megadeth And Slayer To Co-Headline 'Canadian Carnage' Trek”originalet”World Painted Blood””Release “World Painted Blood” by Slayer””Metallica Heading To Cinemas””Slayer, Megadeth To Join Forces For 'European Carnage' Tour - Dec. 18, 2010”originalet”Slayer's Hanneman Contracts Acute Infection; Band To Bring In Guest Guitarist””Cannibal Corpse's Pat O'Brien Will Step In As Slayer's Guest Guitarist”originalet”Slayer’s Jeff Hanneman Dead at 49””Dave Lombardo Says He Made Only $67,000 In 2011 While Touring With Slayer””Slayer: We Do Not Agree With Dave Lombardo's Substance Or Timeline Of Events””Slayer Welcomes Drummer Paul Bostaph Back To The Fold””Slayer Hope to Unveil Never-Before-Heard Jeff Hanneman Material on Next Album””Slayer Debut New Song 'Implode' During Surprise Golden Gods Appearance””Release group Repentless by Slayer””Repentless - Slayer - Credits””Slayer””Metal Storm Awards 2015””Slayer - to release comic book "Repentless #1"””Slayer To Release 'Repentless' 6.66" Vinyl Box Set””BREAKING NEWS: Slayer Announce Farewell Tour””Slayer Recruit Lamb of God, Anthrax, Behemoth + Testament for Final Tour””Slayer lägger ner efter 37 år””Slayer Announces Second North American Leg Of 'Final' Tour””Final World Tour””Slayer Announces Final European Tour With Lamb of God, Anthrax And Obituary””Slayer To Tour Europe With Lamb of God, Anthrax And Obituary””Slayer To Play 'Last French Show Ever' At Next Year's Hellfst””Slayer's Final World Tour Will Extend Into 2019””Death Angel's Rob Cavestany On Slayer's 'Farewell' Tour: 'Some Of Us Could See This Coming'””Testament Has No Plans To Retire Anytime Soon, Says Chuck Billy””Anthrax's Scott Ian On Slayer's 'Farewell' Tour Plans: 'I Was Surprised And I Wasn't Surprised'””Slayer””Slayer's Morbid Schlock””Review/Rock; For Slayer, the Mania Is the Message””Slayer - Biography””Slayer - Reign In Blood”originalet”Dave Lombardo””An exclusive oral history of Slayer”originalet”Exclusive! Interview With Slayer Guitarist Jeff Hanneman”originalet”Thinking Out Loud: Slayer's Kerry King on hair metal, Satan and being polite””Slayer Lyrics””Slayer - Biography””Most influential artists for extreme metal music””Slayer - Reign in Blood””Slayer guitarist Jeff Hanneman dies aged 49””Slatanic Slaughter: A Tribute to Slayer””Gateway to Hell: A Tribute to Slayer””Covered In Blood””Slayer: The Origins of Thrash in San Francisco, CA.””Why They Rule - #6 Slayer”originalet”Guitar World's 100 Greatest Heavy Metal Guitarists Of All Time”originalet”The fans have spoken: Slayer comes out on top in readers' polls”originalet”Tribute to Jeff Hanneman (1964-2013)””Lamb Of God Frontman: We Sound Like A Slayer Rip-Off””BEHEMOTH Frontman Pays Tribute To SLAYER's JEFF HANNEMAN””Slayer, Hatebreed Doing Double Duty On This Year's Ozzfest””System of a Down””Lacuna Coil’s Andrea Ferro Talks Influences, Skateboarding, Band Origins + More””Slayer - Reign in Blood””Into The Lungs of Hell””Slayer rules - en utställning om fans””Slayer and Their Fans Slashed Through a No-Holds-Barred Night at Gas Monkey””Home””Slayer””Gold & Platinum - The Big 4 Live from Sofia, Bulgaria””Exclusive! Interview With Slayer Guitarist Kerry King””2008-02-23: Wiltern, Los Angeles, CA, USA””Slayer's Kerry King To Perform With Megadeth Tonight! - Oct. 21, 2010”originalet”Dave Lombardo - Biography”Slayer Case DismissedArkiveradUltimate Classic Rock: Slayer guitarist Jeff Hanneman dead at 49.”Slayer: "We could never do any thing like Some Kind Of Monster..."””Cannibal Corpse'S Pat O'Brien Will Step In As Slayer'S Guest Guitarist | The Official Slayer Site”originalet”Slayer Wins 'Best Metal' Grammy Award””Slayer Guitarist Jeff Hanneman Dies””Kerrang! Awards 2006 Blog: Kerrang! Hall Of Fame””Kerrang! Awards 2013: Kerrang! Legend”originalet”Metallica, Slayer, Iron Maien Among Winners At Metal Hammer Awards””Metal Hammer Golden Gods Awards””Bullet For My Valentine Booed At Metal Hammer Golden Gods Awards””Metal Storm Awards 2006””Metal Storm Awards 2015””Slayer's Concert History””Slayer - Relationships””Slayer - Releases”Slayers officiella webbplatsSlayer på MusicBrainzOfficiell webbplatsSlayerSlayerr1373445760000 0001 1540 47353068615-5086262726cb13906545x(data)6033143kn20030215029