프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
주어진 문자열의 길이가 4 또는 6인지 확인하고, 모든 문자가 숫자로만 구성되어 있는지 판별하는 문제입니다. 파이썬의 내장 메서드를 활용하는 방법과 정규표현식을 활용하는 방법 두 가지로 해결할 수 있습니다.
1. 나의 풀이
정규표현식을 활용한 풀이
import re
def solution(s):
# 문자열 전체가 숫자 4자 혹은 6자인지 검사
return bool(re.fullmatch(r"\d{4}|\d{6}", s))
내장 메서드를 활용한 풀이
def solution(s):
# 길이를 먼저 확인하고 숫자로만 구성되었는지 검사
if (len(s) == 4 or len(s) == 6) and s.isdigit():
return True
else:
return False
2. 오늘 배운 점 및 복기 노트
정규표현식의 앵커와 울타리 개념
^는 문자열의 시작을, $는 문자열의 끝을 의미합니다. ^[0-9]*$와 같이 양 끝에 앵커를 붙이면 문자열의 시작부터 끝까지 오직 해당 패턴(숫자)만 존재해야 함을 강제합니다. 중간에 다른 문자(예: "123a456")가 섞일 경우 전체 매칭이 실패하게 되는 원리를 확인했습니다.
re.match와 re.fullmatch의 차이점
re.match()는 문자열의 시작 부분이 패턴과 일치하는지 확인하며, re.fullmatch()는 문자열의 처음부터 끝까지 전체가 패턴과 완벽히 일치하는지 확인합니다. 유효성 검사에서는 fullmatch를 사용하는 것이 앵커 생략이 가능하여 더 간결합니다.
수량자 선택의 정교함
*는 0개 이상, +는 1개 이상을 의미합니다. ^[0-9]*$ 패턴은 빈 문자열("")도 숫자가 0개 있는 것으로 간주하여 성공시키지만, 앞단에서 len(s) in {4, 6}과 같이 길이를 미리 제한한다면 *를 사용해도 논리적 오류가 발생하지 않음을 이해했습니다.
3. 프로그래머스 코딩 테스트 문제 풀이 전략 교재에서 배울만한 점
단축 평가를 활용한 성능 최적화
교재에서는 len(s) in {4, 6}을 정규표현식보다 앞에 배치하여 성능을 높였습니다. 파이썬의 and 연산자는 앞의 조건이 거짓이면 뒤의 정규표현식 연산을 아예 수행하지 않는 단축 평가(Short-circuit evaluation)를 수행하기 때문입니다.
구현 편의성과 실행 시간의 트레이드오프
모든 조건을 정규표현식 하나에 담는 방식(r"^(\d{4}|\d{6})$")은 코드가 간결한 반면, 길이를 먼저 체크하는 방식은 불필요한 패턴 매칭 연산을 줄여 실행 시간을 단축합니다. 코딩 테스트 상황에 따라 가독성과 성능 중 우선순위를 결정하는 전략이 필요합니다.
자주 사용하는 유효성 검사 패턴
숫자(^[0-9]*$ 혹은 ^\d*$), 알파벳(^[a-zA-Z]*$), 한글(^[가-힣]*$) 등 고정 형식의 문자열을 검사하는 정규표현식은 실전에서 빈번하게 활용되므로 암기해 두는 것이 유리합니다.
앞뒤에 붙은 ^와 $ 덕분에, 문자열 중간에 패턴과 다른 내용이 있으면 False 처리됩니다.
4. 정규표현식 핵심 기호 요약표
| 분류 | 표현식 | 의미 | 직관적 해석 및 예시 |
| 위치/선택 | ^ | 시작 앵커 | "이걸로 시작해" ^a → "apple" (O), "banana" (X) |
| $ | 종료 앵커 | "이걸로 끝나야 해" z$ → "jazz" (O), "zebra" (X) |
|
| | | 선택(OR) | "이거 아니면 저거" \d{4}|\d{6} → 숫자 4자리 또는 6자리 |
|
| ( ) | 그룹화 | "여러 글자를 하나로 묶음" (abc)+ → "abcabc" (O), "abc" (O) |
|
| 수량자 | * | 0개 이상 | "없어도 되고 많아도 됨" a* → "" (O), "aaaaa" (O) |
| + | 1개 이상 | "무조건 하나는 있어야 함" a+ → "a" (O), "" (X) |
|
| ? | 0 또는 1 | "있을 수도 있고 없을 수도 있음" apples? → "apple" (O), "apples" (O) |
|
| {n} | 정확히 n번 | "딱 n번만 반복" \d{3} → "123" (O), "12" (X) |
|
| {n,} | n번 이상 | "최소 n번 반복" a{2,} → "aa" (O), "a" (X) |
|
| {n,m} | n~m번 | "n번부터 m번 사이" \d{4,6} → 숫자 4, 5, 6자 통과 |
|
| 집합/범위 | [XY] | 문자 집합 | "X 또는 Y 중 한 글자" [aeiou] → 영어 모음 중 한 글자 |
| [^X] | 부정(NOT) | "X만 아니면 됨" ^는 맨 앞일 때만 부정, 그 외에는 일반 문자입니다. [^0-9] → 숫자가 아닌 모든 문자 [^aeiou] → a, e, i, o, u를 제외한 모든 문자 [aeio^u] → 영어 모음 또는 기호 ^ 중 한 글자 |
|
| [A-Z] | 범위 지정 | "A부터 Z까지 사이의 문자" [a-z] (소문자), [0-9] (숫자) |
|
| 단축 클래스 | \d | 숫자 | [0-9]와 동일 |
| \D | 숫자가 아님 | [^0-9]와 동일 | |
| \w | 문자+숫자+_ | [a-zA-Z0-9_]와 동일 | |
| \W | \w가 아님 | 특수문자 등 공백 제외 문자 | |
| \s | 공백 문자 | 탭, 줄바꿈, 띄어쓰기 등 | |
| \S | 공백이 아님 | 공백을 제외한 모든 문자 |
대문자와 시작 앵커의 차이
- 정규표현식의 단축 클래스에서 대문자(\D, \W, \S)는 항상 소문자의 반대(NOT)를 의미합니다.
- ^는 대괄호 밖 ^a 에서는 시작을 뜻하지만, 대괄호 안 [^a] 에서는 제외를 뜻합니다.
5. 파이썬 re 모듈 활용 가이드
re 모듈의 주요 함수 활용법 파이썬에서 정규표현식을 사용할 때는 re 라이브러리를 임포트하며, 목적에 따라 아래 함수들을 선택하여 사용합니다.
import re
# 1. match: 문자열 '시작'부터 패턴이 일치하는지 확인
# 시작이 숫자면 Match 객체 반환, 아니면 None 반환
re.match(r'\d+', '123ab') # <re.Match object; span=(0, 3), match='123'>
re.match(r'\d+', 'a123b') # None (시작이 문자이므로)
# 2. fullmatch: 문자열 '전체'가 패턴과 완벽히 일치하는지 확인
# 전체가 숫자여야만 성공
re.fullmatch(r'\d+', '123') # <re.Match object; span=(0, 3), match='123'>
re.fullmatch(r'\d+', '123ab') # None (문자가 섞여 있어 불일치)
# 3. search: 문자열 '어디든' 패턴이 포함되어 있는지 확인
# 위치와 상관없이 첫 번째로 발견된 패턴 매칭
re.search(r'\d+', 'a123b') # <re.Match object; span=(1, 4), match='123'>
# 4. findall: 패턴과 일치하는 모든 부분을 리스트로 반환
# 문자열 내 모든 숫자 뭉치를 추출할 때 유용
re.findall(r'\d+', '12a34b56') # ['12', '34', '56']
# 5. sub: 패턴과 일치하는 부분을 다른 문자로 치환
# 숫자 부분을 모두 '*'로 변경
re.sub(r'\d+', '*', '12a34b') # '*a*b'
Raw String(r"") 사용
정규표현식에는 백슬래시(\)가 자주 등장합니다. 파이썬 문자열에서 백슬래시는 이스케이프 문자로 인식되므로, 이를 방지하기 위해 정규표현식 패턴 앞에는 반드시 r을 붙여 Raw String임을 명시하는 것이 안전합니다.
# 일반 문자열은 백슬래시를 두 번 써야 함
pattern = "\\d+"
# Raw String을 쓰면 한 번만 써도 됨 (권장)
pattern = r"\d+"
불리언(Boolean) 변환
re.match() 등의 함수는 성공 시 Match 객체를, 실패 시 None을 반환합니다. 이를 if 조건문에 직접 넣거나 bool() 함수로 감싸면 간단하게 참/거짓 값을 얻을 수 있습니다.
'알고리즘 > 프로그래머스 문제 풀이 전략' 카테고리의 다른 글
| 정규 표현식 추가문제 - 파일명 정렬 (Python) (0) | 2026.04.27 |
|---|---|
| 문제 15 - 핸드폰 번호 가리기 (Python) + 특수 목적 정규식 (0) | 2026.04.27 |
| 문제13 - 신규 아이디 추천 (Python) (0) | 2026.04.26 |
| 문제12 - 이진 변환 반복하기 (Python) (0) | 2026.04.26 |
| 문제11 - 3진법 뒤집기 (Python) (0) | 2026.04.26 |
