[카카오] 카카오 신규 아이디 추천 코드- regex 정규식 사용하기 (Python)
Updated:
2021년 카카오 블라인드 채용 코딩테스트중, 기본 문제 “카카오 신규 아이디 추천”의 코드와 풀이입니다. 정규식을 사용하면 원하는 문자열 그룹을 아주 쉽게 정의할 수 있습니다. 쉽게 풀어놨으니 꼭 찬찬히 보고 이해해보세요!
정규식 관련해서는, 앨리님 사이트를 참고 하고 이 사이트에서 연습하며 풀어봤습니다.
- 사용되는 정규식
- 1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
- [2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.](#2단계-new_id에서-알파벳-소문자-숫자-빼기–밑줄-마침표를-제외한-모든-문자를-제거합니다)
- 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
- 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
- 5단계 new_id가 빈 문자열이라면, new_id에 “a”를 대입합니다.
- 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 6.1 6-1 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
- 7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다. 전체 코드
인풋 & 아웃풋 예제
인풋 | 아웃풋 |
---|---|
...!@BaT#*..y.abcdefghijklm |
bat.y.abcdefghi |
z-+.^. |
z-- |
=.= |
aaa |
123_.def |
123_.ded |
abcdefghijklmn.p |
abcdefghijklmn |
사용되는 정규식
정규식 | 의미 |
---|---|
[^] | 부정 문자셋, 괄호안의 어떤 문자가 아닐 때 |
[a-zA-Z0-9] | 알파벳 a부터 z 까지, 대문자 A부터 Z까지, 숫자 0-9까지의 문자셋 |
. | 특문 마침표 (.) |
(문자){2,} | (문자가) 최소 두번 반복 (최대는 정의되지 않았으니 무한대) |
^(문자) | (문자가)문장의 앞에 있을때 |
(문자)$ | 문장의 뒤에 있을때 (문자가) |
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
answer = new_id.lower()
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
정규식
- 여기서 regex, regular expression 즉 정규식을 사용하게 됩니다. 다수의 룰로 문자열을 제한하는거죠.
[^a-zA-Z0-9_-.]
[^]
: negate, 부정 문자셋, 괄호안의 어떤 문자가 아닐떄a-z
: 알파벳 a부터 z까지A-Z
: 알파벳 대문자 A부터 Z까지0-9
: 숫자 0-9까지_-.
: 특수문자 - (빼기), _ (언더스코어), .(마침표)
상위 표현은 a-z,A-Z,0-9,-_. 의 문자셋이 아닐
경우를 말합니다. 그러면 !@# 등의 특문은 제외되는거겠죠? 우리가 딱 원하는 식입니다.
코드
answer = re.sub("[^a-z0-9-_.]", "", new_id)
이것을 코드로 적용하면 이렇게 됩니다. sub, 즉 대체하다 substitute (대상, 대체할 내용, 해당 변수) 입니다.
new_id
에서[^a-z0-9-_.]
에 해당하는 문자열을""
빈 문자열로 대체시킴
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
answer = re.sub("\.{2,}", ".", answer)
\.
: 특문 마침표{2,}
: 최소 2번 반복
그럼 특수문자 마침표가 2번 반복된 부분을 찾는 정규식이 됩니다. 위와 같은 sub 함수를 쓰며, 마침표가 최소 2번 이상 반복된 구간을 마침표 하나로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
answer = re.sub ("^\.|\.$" ,"", answer)
^\.
: 특문 마침표가 . 처음에 있거나|
: OR, 또는\.$
: 특문 마침표 .가 끝에 있으면
”” 로 치환함으로써 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 “a”를 대입합니다.
if answer == "":
answer = "a"
직관적인 코드입니다. 앞의 프로세스를 반복하면서/ 원래 문자열 answer 가 빈 문자열이 되었다면, a 를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
if len(answer) > 15:
answer = answer[:15]
여기서는 파이썬 slice 함수를 사용했습니다. 만약 answer의 길이가 15자 초과 (16자 미만) 이면, 문자열을 슬라이스하라
string[:슬라이스될자리]
: 스트링 문자열의 15번째 캐릭터에서 문자열을 잘라라
6-1 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
answer = re.sub("\.$", "", answer)
4단계와 같은 코드입니다.
\.
: 특문 마침표가$
: 문장 끝에 있으면
빈 문자열로 치환하라 (=제거하라)
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
while True:
if len(answer) > 2:
break
answer = answer + answer[-1]
파이썬 슬라이스 함수를 다시 사용했습니다.
- string[-1] : 스트링의 마지막 캐릭터를 의미합니다. answ[-1]의 결괏값은 w 입니다.
고로, answer의 길이가 2가 넘지 않는 이상, 마지막 캐릭터를 계속 갖다 붙여라 - 가 되겠습니다.
전체 코드
import re
def solution(new_id):
answer = ''
# 1 & 2. lowercase and remove except '!', '@', '#', '*'
answer = re.sub('[^a-z0-9-_.]', '', new_id.lower())
# 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
answer = re.sub('\.{2,}', '.', answer)
# 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
answer = re.sub('^\.|\.$', '', answer)
# 5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
if answer == '':
answer = 'a'
# 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
if len(answer) > 15:
answer = answer[:15]
# 6.2 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
answer = re.sub('\.$' , '', answer)
# 7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
while True:
if len(answer) > 2:
break
answer = answer + answer[-1]
return answer
print(solution("...!@BaT#*..y.abcdefghijklm."))
print(solution("123_.def"))
이상입니다! 이해 잘 되셨길 바랍니다.
Leave a comment