VIN Checker
In this Kata you should write a function to validate VINs, Vehicle Identification Numbers. Valid VINs are exactly 17 characters long, its composed of capital letters (except "I","O" and "Q") and digits. The 9th character is a MODULUS 11 check digit. Here is how it works:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1 2 3 4 5 6 7 8 1 2 3 4 5 7 9 2 3 4 5 6 7 8 9
Ex.: VIN 5YJ3E1EA7HF000337 becomes 58135151786000337.
[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2]
Ex.:
VIN: 5 Y J 3 E 1 E A 7 H F 0 0 0 3 3 7
DECODED: 5 8 1 3 5 1 5 1 7 8 6 0 0 0 3 3 7
WEIGHTS: 8 7 6 5 4 3 2 10 0 9 8 7 6 5 4 3 2
PRODUCT: 40 56 6 15 20 3 10 10 0 72 48 0 0 0 12 9 14
Ex.:
40+56+6+15+20+3+10+10+0+72+48+0+0+0+12+9+14 = 315
Ex.:
315 mod 11 = 7
Ex.:
5YJ3E1EA7HF000337 is a valid VIN, 9th character is 7
Note
If the modulus 11 of the sum is equal to 10, then the digit is "X".
Ex.:
5YJ3E1EAXHF000347 is a valid VIN.
Input Validation
Input validation is part of the Kata, VINs with lenghts different than 17 characters or containing invalid characters should return False as well.
None
"5YJ3E1EA7HF000337" True
"5YJ3E1EAXHF000347" True
"5VGYMVUX7JV764512" True
"7WDMMTDV9TG739741" False
"7JTRH08L5EJ234829" False
import re
def check_vin(number):
if len(number) == 17: #길이검사
is_invalid = re.findall('[^A-HJ-NPR-Z0-9]+', number) #유효문자검사
if not is_invalid:
#계산용
weight = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2]
#컨버팅용
num_dic = {'A':1, 'B':2, 'C':3, 'D':4, 'E':5, 'F':6, 'G':7, 'H':8,
'J':1, 'K':2, 'L':3, 'M':4, 'N':5, 'P':7, 'R':9,
'S':2, 'T':3, 'U':4, 'V':5, 'W':6, 'X':7, 'Y':8, 'Z':9}
#해독된 숫자
decoded_number = list(map(lambda x : num_dic[x] if x.isalpha() else int(x), number))
# 최종값
final_num = sum([x*y for x,y in zip(weight, decoded_number)]) % 11
# 분기처리
if final_num == 10 and number[8] == 'X':
return True
# 조건엔 없는데 'X'가 오는경우는 final_num이 무조건 10 외에는 안됨
# (이것때문에 풀이시간 지체 엄청 되었음)
elif final_num == decoded_number[8] and number[8] != 'X':
return True
return False
TRANS = str.maketrans("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z",
"1 2 3 4 5 6 7 8 1 2 3 4 5 7 9 2 3 4 5 6 7 8 9")
WEIGHTS = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2]
def check_vin(vin):
try:
return len(vin) == 17 and vin[8] == "0123456789X"[sum(int(c) * w for c, w in zip(vin.translate(TRANS), WEIGHTS)) % 11]
except:
return False
파이써닉하고 간결한 풀이, 그저 아름답네요.
전 언제 이 수준까지 가서 능수능란하게 trans를 떠올리고 try except와 문자열 슬라이싱으로 정리해버릴수 있을런지.. 🤔