신용카드 번호가 주어졌을 때, 그 번호가 유효한지 아닌지를 판별해야 하는 상황을 생각해 볼 수 있습니다. 유효한 카드 번호는 다음과 같은 규칙을 만족해야 합니다.
- 번호는 4, 5 또는 6으로 시작해야 합니다.
- 전체 길이는 정확히 16자리여야 합니다.
- 숫자만 포함해야 합니다.
- 필요하다면 하이픈(-)으로 구분된 네 개의 그룹(각 그룹 4자리) 형태로 표기할 수 있습니다.
- 공백이나 밑줄(_) 같은 다른 구분 기호는 사용할 수 없습니다.
- 같은 숫자가 4번 이상 연속으로 나타나서는 안 됩니다.
예를 들어 입력이 s = "5423-2578-8632-6589"라면 위 조건을 모두 충족하므로 결과는 True입니다.
문제 해결 접근 방법
- 문자열에 하이픈(-)이 포함되어 있는지 확인합니다.
- 하이픈이 있다면 문자열을 분리해 그룹이 정확히 4개이고 각 그룹이 4자리인지 검사합니다.
- 하이픈을 제거한 전체 번호가 4, 5 또는 6으로 시작하고 뒤이어 15자리 숫자가 오는지 정규식으로 확인합니다.
- 같은 숫자가 4회 이상 연속으로 반복되는 패턴이 있는지 검사합니다.
- 모든 조건을 통과하면
True, 하나라도 어긋나면False를 반환합니다.
구현 예시
다음은 위 로직을 파이썬으로 구현한 코드입니다.
import re
def solve(s):
# 하이픈이 있으면 그룹 형식 검사
if "-" in s:
groups = s.split("-")
if len(groups) != 4 or any(len(g) != 4 for g in groups):
return False
# 하이픈 제거 후 전체 번호 검사
number = s.replace("-", "")
# 4, 5, 6으로 시작하는 16자리 숫자인지 확인
start_ok = re.fullmatch(r"[456][0-9]{15}", number)
# 같은 숫자가 4번 이상 연속으로 반복되는지 확인
repeated = re.search(r"([0-9])\1{3}", number)
return bool(start_ok) and repeated is None
s = "5423-2578-8632-6589"
print(solve(s))
입력
"5423-2578-8632-6589"
출력
True
코드 핵심 포인트
re.fullmatch(r"[456][0-9]{15}", number): 문자열 전체가 4, 5, 6으로 시작하는 16자리 숫자인지 검사합니다.search대신fullmatch를 사용하면 부분 일치로 인한 오탐을 방지할 수 있습니다.r"([0-9])\1{3}": 임의의 한 자리 숫자를 캡처한 뒤 역참조(\1)로 같은 숫자가 세 번 더 반복되는 패턴을 찾아, 동일 숫자 4연속 여부를 확인합니다.- 하이픈 그룹 검사는
split과len만으로 간단하게 처리할 수 있습니다.
유효 · 무효 예시 비교
- 유효:
"5123-4567-8912-3456","6011123456781234" - 무효:
"1234-5678-9123-4567"(1로 시작) - 무효:
"4444-1111-2222-3333"(같은 숫자 4연속) - 무효:
"5123 4567 8912 3456"(허용되지 않는 공백 구분자) - 무효:
"51234567-8912-3456"(그룹 크기 불일치)
참고로 실제 결제 시스템에서는 위 형식 검사 외에도 Luhn 알고리즘(체크섬 검증)을 함께 사용해 카드 번호의 진위를 더 엄격하게 확인합니다. 학습 목적의 문제라면 위 규칙만으로 충분하지만, 실무에서는 Luhn 검사를 추가로 구현하는 것이 좋습니다.