Поиск четных и нечетных цифр для проверки кредитной карты

#python #string #slice

#python #строка #срез

Вопрос:

Я прошел курс CS50, и это мой первый раз, когда я использую Python. Я работаю над проблемой 6 — кредитной карты. Это мой код:

 from cs50 import get_string
from itertools import chain
import re

def main():
    # get credit card number from user
    credit_card = get_string("Number: ")

    # take odd and even number from Credit Card and then store it in reversed
    # 4003600000000014 || even = 10000604 || count from last-to-second

    even =''.join(reversed (re.findall("w",credit_card[::2])))
    odd =''.join(reversed (re.findall("w",credit_card[1::2])))

    # convert strings to integer
    even = [int(i) for i in even]
    odd = [int(i) for i in odd]

    
    # add each number in the list
    # BUT for SUM_EVEN number, multiply each digit by 2. and there will be the case the result is greater than 9
    # ex : 6 * 2 = 12 || so we need to seperate it (12 = 1   2)
    
    sum_even = sum([int(((2 * x) % 10)   ((2 * x)) / 10) for x in even])
    sum_odd = sum(odd)
    checksum = sum_even   sum_odd
    

    # FIND first digit and first two digit
    first_digit = int(credit_card[0:1])
    first_two_digit = int(credit_card[0:2])
    

    # VALIDATE the credit card and check which company by its structure
    if checksum % 10 == 0:
        if first_digit == 4 and (len(credit_card) == 13 or len(credit_card) == 16):
            print("VISA")
        elif (first_two_digit == 34 or first_two_digit == 37) and len(credit_card) == 15:
            print("AMEX")
        elif (first_two_digit >= 51 and first_two_digit <= 55) and len(credit_card) == 16:
            print("MASTERCARD")
        else:
            print("INVALID")
    else:
        print("INVALID")


main()
  

4003600000000014

Итак, нам нужно получить предпоследнюю цифру (или мы можем назвать ее ЧЕТНЫМ числом) на кредитной карте, а затем умножить каждую цифру на 2. Затем мы суммируем с нечетным числом.

Дело в том, что мой код почти успешен. Он успешно печатает кредитные карты VISA и MASTERCARD. Но для AMEX это всегда НЕДОПУСТИМО. Позже я узнал, что кредитная карта AMEX использует 15-значные числа. MASTERCARD использует 16-значные числа. VISA использует 13 или 16-значные числа.

Для нечетной цифры (13 или 15) мой код не принимал ЧЕТНЫЕ и нечетные числа так же, как ЧЕТНУЮ цифру (16).

 for example: 

VISA : 4003600000000014
even: [1, 0, 0, 0, 0, 6, 0, 4]
odd: [4, 0, 0, 0, 0, 0, 3, 0]

but for AMEX: 378282246310005
even: [5, 0, 1, 6, 2, 8, 8, 3]
odd: [0, 0, 3, 4, 2, 2, 7]
  

Вы видите? AMEX ‘even’ не начинался со предпоследней цифры, как это делала VISA. На самом деле четные и нечетные меняются местами.

Итак, я знаю, что в этом коде есть ошибка, которую я нашел сам:

 even =''.join(reversed (re.findall("w",credit_card[::2])))
odd =''.join(reversed (re.findall("w",credit_card[1::2])))
  

Есть ли что-то, что мне нужно изменить с помощью кода, чтобы определить, является ли цифра 13, 15 или 16. Или, возможно, мой код неверен, и мне нужно использовать другой код, чтобы найти ЧЕТНЫЙ и нечетный номер на кредитной карте.

Комментарии:

1. re.findall() Вызов кажется ненужным (при credit_card условии, что переменная содержит только числа). Simply even = credit_card[::2] предоставит вам четные цифры и odd = credit_card[1::2] даст вам нечетные цифры.

2. Он по-прежнему НЕДЕЙСТВИТЕЛЕН для и только для AMEX: (Я думаю, что что-то не так с подстрокой. Он не обрабатывал кредитную карту с нечетной (15, 13) цифрой в хорошем смысле.

3. Доступна ли где-нибудь исходная постановка задачи? Немного сложно сказать, что должна делать ваша программа.

4. Это полное объяснение, но для C: cs50.harvard.edu/x/2020/psets/1/credit — и это для Python. Что не является объяснением: cs50.harvard.edu/x/2020/psets/6/credit

5. @Kevinkun Можете ли вы подтвердить, что мой ответ решает вашу проблему? Мне кажется, что это работает нормально, когда я пробую это с вашим кодом.

Ответ №1:

В задаче указано, что вы должны принимать все остальные цифры, начиная со предпоследней цифры. Но, как вы обнаружили, это не то же самое, что просто брать четные и нечетные цифры числа, поскольку это даст разные результаты для чисел с нечетной или четной длиной. Решение состоит в том, чтобы сначала перевернуть число, а затем взять его четные и нечетные цифры:

 # reverse the digits
cc_reversed = credit_card[::-1]
print(cc_reversed)

# convert to integers
even = [int(i) for i in cc_reversed[1::2]]
odd = [int(i) for i in cc_reversed[::2]]
print(even)
print(odd)
  

Для 4003600000000014 (VISA) выводится:

 4100000000063004
[1, 0, 0, 0, 0, 6, 0, 4]
[4, 0, 0, 0, 0, 0, 3, 0]
  

и для 378282246310005 (AMEX) он печатает:

 500013642282873
[0, 0, 3, 4, 2, 2, 7]
[5, 0, 1, 6, 2, 8, 8, 3]
  

Итак, теперь список четных цифр всегда будет начинаться с предпоследней цифры исходного номера (т. Е. 1 Для VISA и 0 для AMEX в приведенных выше примерах).

Обновить:

Чтобы уточнить, вот более простой пример:

 >>> '0010'[::2] # even digits
'01'
>>> '0010'[::2][::-1] # even digits, reversed
'10'
  

Для чисел четной длины четные цифры всегда будут заканчиваться на предпоследней цифре (чего мы и хотим). Но это никогда не будет работать для чисел нечетной длины, потому что это всегда будет заканчиваться на последней цифре:

 >>> '00010'[::2] # even digits
'000'
  

Вместо этого нам нужно взять все остальные цифры, начиная со второй по последнюю цифру. Это можно гарантировать, сначала изменив номер:

 >>> '0010'[::-1] # reversed
'0100'
>>> '0010'[::-1][1::2] # reversed, every other digit
'10'
>>> '00010'[::-1] # reversed
'01000'
>>> '00010'[::-1][1::2] # reversed, every other digit
'10'
  

На самом деле говорить о четных и нечетных цифрах вводит в заблуждение. Что действительно важно, так это убедиться, что вы всегда начинаете с одного и того же места.