[프로그래머스] 신규 아이디 추천 - python 본문

코테 문제 풀이

[프로그래머스] 신규 아이디 추천 - python

미니모아 2022. 3. 28. 18:15
반응형

신규 아이디 추천

문제

신규 유저가 입력한 아이디를 나타내는 new_id가 매개변수로 주어질 때, "네오"가 설계한 7단계의 처리 과정을 거친 후의 추천 아이디를 return 하도록 solution 함수를 완성해 주세요.

1단계 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개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

제한사항

new_id는 길이 1 이상 1,000 이하인 문자열입니다. new_id는 알파벳 대문자, 알파벳 소문자, 숫자, 특수문자로 구성되어 있습니다. new_id에 나타날 수 있는 특수문자는 -_.~!@#$%^&*()=+[{]}:?,<>/ 로 한정됩니다.

풀이

def solution(new_id):
    answer = ''
    available = ["-", "_", "."]
    # 1
    new_id = new_id.lower()
    # 2
    new_id = ''.join(x for x in new_id if x.isalpha() or x.isdigit() or x in available)

    cnt = 0
    new_id_tmp = ''
    # 3
    for i in range(len(new_id)):
        if new_id[i] == ".":
            cnt += 1
        else:
            if cnt >= 1:
                new_id_tmp += '.'
                cnt = 0

            new_id_tmp += new_id[i]

    if cnt >= 2:
        new_id_tmp += '.'
        cnt = 0
​


    # 4

    new_id = new_id_tmp.strip(".")

    # 5
    if new_id == '':
        new_id = 'a'

    # 6
    if len(new_id) >= 16:
        new_id = new_id[:15]
        if new_id[-1] == ".":
            new_id = new_id[:-1]
    # 7
    if len(new_id) <= 2:
        while len(new_id) != 3:
            new_id += new_id[-1]

    return new_id

1단계는 list comprehension을 이용해서 해당 문자들만 남기고 join으로 문자열을 만들어주면 쉽게 처리할 수 있다.

처음에는 3단계를 replace를 이용해서 구현했는데 이 경우 아래와 같은 반례가 존재해서 통과 못한 테스트 케이스가 생겼다.

입력
".........-.........-...-...-..-.."
​
출력
"-.-.-.-.-"

그래서 새로문 문자열을 만들어서 연속된 마침표의 개수를 세고 마침표가 아닌 시점에서 cnt가 2이상일 경우 마침표를 더하고 현재 문자를 더하도록 했다.

 

근데 그냥 이렇게 처리했으면 됐다.

while '..' in answer:
        answer = answer.replace('..', '.')

 

4단계는 strip를 이용하면 쉽게 처리할 수 있다. 양 끝의 해당하는 문자를 지워준다.

 

정규식을 이용한 방법

훨씬 간단함

import re
​
def solution(new_id):
    st = new_id
    st = st.lower()
    st = re.sub('[^a-z0-9\-_.]', '', st)
    st = re.sub('\.+', '.', st)
    st = re.sub('^[.]|[.]$', '', st)
    st = 'a' if len(st) == 0 else st[:15]
    st = re.sub('^[.]|[.]$', '', st)
    st = st if len(st) > 2 else st + "".join([st[-1] for i in range(3-len(st))])
    return st

문자 클래스 []

[ ] 사이의 문자들과 매치

  • [a-zA-Z] : 알파벳 모두
  • [0-9] : 숫자

^

  • 문자 클래스 안에 ^ 메타 문자를 사용할 경우에는 반대(not)라는 의미
  • 예) [^0-9] 숫자가 아닌 것들만 매치
  • 문자열 맨 처음과 일치한다는 의미 (문자 클래스 안이 아닐 때)

\

문자 그 자체라는 것를 표시하기 위해서

(. 단독으로 쓰면 정확히 1개 문자 매칭이라는 뜻)

$

$는 문자열의 끝과 매치한다는 의미

|

or의 의미

+

1번 이상 반복되는 문자 매칭 (0번 이상 반복되는 문자 매치는 *)

정규식 참고

https://chrisjune-13837.medium.com/%EC%A0%95%EA%B7%9C%EC%8B%9D-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%9C-cheatsheet-%EB%B2%88%EC%97%AD-61c3099cdca8

반응형
Comments