#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
условии, что переменная содержит только числа). Simplyeven = 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'
На самом деле говорить о четных и нечетных цифрах вводит в заблуждение. Что действительно важно, так это убедиться, что вы всегда начинаете с одного и того же места.