신규아이디추천(72410)
문제 이해:
입력된 문자열을 정해진 규칙에 따라 변환해야하는 문제이다.
시도 1: if문과 반복문 사용하기
반복문으로 문자열을 순회하며 조건문을 통해 새로운 문자열을 만들어나가는 식으로 주어진 규칙을 구현하는 방식의 풀이를 진행하였다.
def solution(new_id):
sol=''
answer = '.'+new_id.lower() + '.' # 맨 앞, 뒤에 . 추가(추후 설명)
for s in answer: # 각 문자가 -._아닌 특문인지 확인
if s in '~!@#$%^&*()=+[{]}:?,<>/':
continue
sol+=s# 아닌 경우에만 살린다.
answer=sol # 임시저장
sol='.'
for s in answer: # 연속되는 . 하나만 남기기
if s== '.' and s == sol[-1]: # 가장 최근에 추가된 것과 일치하는데 그게 . 이면 스킵
continue
sol+=s
sol= sol[1:-1] if len(sol)>2 else 'a' # 문자열이 '..'인 경우 'a'로 치환
if len(sol)>15:
sol=sol[:15] if sol[14]!='.' else sol[:14]
if len(sol)<3:
sol += sol[-1]*(3-len(sol))
return sol
먼저 주어진 아이디의 대문자를 모두 소문자로 바꾼뒤 앞 뒤로 . 을 하나씩 붙인다. 이렇게 한 이유는 문자열의 내용이 어떻든 간에 나중에 문자열 앞 뒤의 .을 제거할 때 반드시 앞 뒤에 .이 하나씩 있어 무조건 인덱스 에러 없이 제거할 수 있기 때문이다.
이후 반복문에서 특수문자가 나오면 새 빈 문자열이 추가안하고 그 이외의 것은 이어붙이는 식으로 걸러내고
연속된 .의 제거도 반복문을 통해 진행한다.
이후 앞 뒤의 . 을 제거하는데, 이때 길이가 2 이하인 경우 '..'임을 의미하고 이는 그냥 빈 문자열과 동일하므로 'a'로 치환하면 된다.
길이에 따른 처리를 한 뒤 반환한다.
이 방식은 빠르긴하나 코드가 길고 복잡하여 정규식을 사용해 풀어보기로 했다.
시도2. 정규식과 re.sub() 사용
def solution(new_id):
new_id = new_id.lower()
new_id = re.sub('[^a-z0-9\._-]', '', new_id) # 알파벳, 숫자, -_.이 아닌 문자 제거
new_id = re.sub('\.+', '.', new_id) # .이 하나 이상 연속된 패턴을 . 으로 치환
new_id = re.sub('^\.|\.$', '', new_id) # 문자열 앞 또는 뒤의 . 제거
if not new_id:
return 'aaa' # 빈 문자열일 경우 'a' 로 치환하는데 어차피 3개맞춰야하니 'aaa' 바로 반환
new_id = new_id[0:15] # 16이상일 경우 15글자 까지만
new_id = re.sub('\.$', '', new_id) # 맨 뒤의 . 제거
return new_id
re.sub()는 정규표현식, 바꿔넣을 문자열, 패턴을 찾을 문자열을 인자로 받아 주어진 문자열에서 정규표현식과 일치하는 패턴을 찾아내 치환하는 함수이다.
이것을 이용해 정규 표현식을 이해할 수 있다면 매우 간결하고 이해하기 좋은(?) 코드를 작성할 수 있었다.
사용된 정규 표현식의 문법은 다음과 같다:
[ ]: 안에 있는 문자와 일치하는 경우를 찾는다. ^ 이 들어갈 경우 반대로 일치하지 않는 경우를 찾는다.
+: 1회 이상의 반복을 의미한다. 'ab+c' 면 abc, abbc, abbbc는 일치하는 패턴이고, ac는 불일치한다. * 은 0회 이상의 반복을 의미하므로 ac도 포함한다. {m,n}으로 반복 횟수를 지정하기도 한다. ab{1,}c는 ab+c와 같다.
\ : 이스케이프 문자를 표시하거나, 메타문자를 그냥 문자 자체로 쓰기 위해 앞에 붙인다. 여기서는 '모든 문자'를 의미하는 . 을 그냥 . 으로 쓰기 위해 붙였다.
| : 여러 패턴을 함께 탐색하기 위해 사용한다. (or)
^, $: 각각 문자열의 머리와 꼬리를 의미한다. '\.$' 는 '문자열 끝에 오는 .' 을 의미한다.
해결. 무엇이 더 나은가?
속도 자체는 시도 1이 더 빨랐다(위가 시도2, 아래가 시도1). 그러나 정규식을 사용한 방식이 더 간결하고 정규식 문법에 대한 이해만 있다면 작성하기도 편했다.
배운점
1. 정규 표현식의 문법 중 반복, 메타문자의 역할을 복습하였다.
2. re.sub()함수의 활용에 대해 알게 되었다.
'코딩테스트풀이' 카테고리의 다른 글
23.05.04 페어프로그래밍: 롤케이크 자르기 (0) | 2023.05.04 |
---|---|
23.05.01 -프로그래머스:햄버거 만들기 (0) | 2023.05.01 |
코딩테스트: 모듈러 연산의 특성과 파이썬 int특성(04.07) (0) | 2023.04.09 |
코딩테스트: zip() 활용 (04.06) (0) | 2023.04.07 |
코딩테스트: 소수와 관련된 문제 3가지(04.05) (0) | 2023.04.06 |