[카카오] 카카오 신규 아이디 추천 코드- regex 정규식 사용하기 (Python)

3 minute read

Updated:

2021년 카카오 블라인드 채용 코딩테스트중, 기본 문제 “카카오 신규 아이디 추천”의 코드와 풀이입니다. 정규식을 사용하면 원하는 문자열 그룹을 아주 쉽게 정의할 수 있습니다. 쉽게 풀어놨으니 꼭 찬찬히 보고 이해해보세요!

정규식 관련해서는, 앨리님 사이트를 참고 하고 이 사이트에서 연습하며 풀어봤습니다.

  1. 사용되는 정규식
  2. 1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
  3. [2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.](#2단계-new_id에서-알파벳-소문자-숫자-빼기–밑줄-마침표를-제외한-모든-문자를-제거합니다)
  4. 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
  5. 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
  6. 5단계 new_id가 빈 문자열이라면, new_id에 “a”를 대입합니다.
  7. 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 6.1 6-1 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
  8. 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