코딩테스트 문제

[프로그래머스/Python] 신규 아이디 추천

왕초보코딩러 2024. 4. 18. 09:35
728x90

문제

https://school.programmers.co.kr/learn/courses/30/lessons/72410

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 


 

정규식을 사용하자!

2024.04.15 - [Python] - 정규식(regular expression)

 

정규식(regular expression)

re모듈을 통해 사용 import re 문자열에 대한 연산에 사용. 문자열 패턴 표현, 문자열 수정, 분할 많이 쓰는 패턴 패턴 설명 ^패턴 이 패턴으로 시작해야 함 패턴$ 이 패턴으로 끝나야 함 패턴1|패턴2

dogfoot1.tistory.com

 

카카오 아이디 규칙 단계

1단계: 모든 대문자 -> 소문자

lower() 를 사용합니다.

# 1단계
part1 =new_id.lower()


2단계: 알파벳 소문자, 숫자, -, _, .가 아닌 것은 제거

이미 대문자는 제거되었기 때문에 a-z가 아닌 \w를 사용할 수 있다.

# 2단계 (알파벳, - _ . 이 아닌 것이 있다면 빈 문자열로 대체)
part2 = re.sub(r'[^\w\-.]', '', part1)


3단계: .가 두 번 이상 연속되면 하나로 치환

# 3단계 (.이 2개 이상인 것이 있다면 빈 문자열로 대체)
part3 = re.sub(r'[.]{2,}', '.', part2)


4단계: .가 문자 맨 앞 맨 뒤에 위치한다면 제거

# 4단계 (.로 시작하거나 끝나는 패턴이 있다면 빈 문자열로 대체)
part4 = re.sub(r'^[.]|[.]?$', '', part3)


5단계: 빈 문자열이라면 "a" 추가

# 5단계 (아이디가 빈 문자열이면 "a"로 하고 아니면 그대로)
part5 = "a" if part4 == "" else part4


6단계: 16자 이상이면 맨 앞부터 15자만 추출

# 6단계 (길이가 15 이하면 그대로, 아니면 맨 앞에서부터 15개를 자르고 .으로 끝나면 .도 없앤다)
part6 = part5 if len(part5) <= 15 else re.sub(r'[.]$', '', part5[:15])


7단계: 길이가 2자 이하면 마지막 문자를 반복해서 3글자 만들기

문자열 * n: 문자열을 n번 반복하기 

문자열 + 문자열: 문자열 합치기

# 7단계 (길이가 3 이상이면 그대로, 아니면 맨 뒤의 글자 (3-len(part6))번 반복해서 3자 만들기)
part7 = part6 if len(part6) >= 3 else part6 + part6[-1]*(3-len(part6))

 

 

우선 잘 알아보기 위해 입출력 예시처럼 만들어보겠습니다.

 

입출력 예시 함수

def propose_id(origin_id):
    ### 1단계 ###
    part1 =origin_id.lower()
    if re.findall(r'[A-Z]', origin_id):
        print(f'1단계 "{origin_id}" -> "{part1}"')
    else:
        print("1단계 변화 없습니다.")
        
    ### 2단계 ###
    part2 = re.sub(r'[^\w\-.]', '', part1)
    if re.findall(r'[^\w\-.]', part1):
        print(f'2단계 "{part1}" -> "{part2}"')
    else:
        print("2단계 변화 없습니다.")
        
    ### 3단계 ###
    part3 = re.sub(r'[.]{2,}', '.', part2)
    if re.findall(r'[.]{2,}', part2):
        print(f'3단계 "{part2}" -> "{part3}"')
    else:
        print("3단계 변화 없습니다.")
    
    ### 4단계 ###
    part4 = re.sub(r'^[.]|[.]?$', '', part3)
    if (re.search(r'^[.]|[.]$', part3)):
        print(f'4단계 "{part3}" -> "{part4}"')
    else:
        print("4단계 변화 없습니다.")
        
    ### 5단계 ###
    part5 = "a" if part4 == "" else part4
    if part4 == "":
        print(f'5단계 "" -> "{part4}"')
    else:
        print("5단계 변화 없습니다.")
        
    ### 6단계 ###
    part6 = part5 if len(part5) <= 15 else re.sub(r'[.]$', '', part5[:15])
    if len(part4) > 15:
        print(f'6단계 "{part4}" -> "{part6}"')
    else:
        print("6단계 변화 없습니다.")
        
    ### 7단계 ###
    part7 = part6 if len(part6) >= 3 else part6 + part6[-1]*(3-len(part6))
    if len(part6) < 3:
        print(f'7단계 "{part6}" -> "{part7}"')
    else:
        print("7단계 변화 없습니다.")
    
    return part7

 

검사

ids = '''...!@BaT#*..y.abcdefghijklm
z-+.^.
=.=
123_.def
abcdefghijklmn.p'''

for d in ids.split('\n'):
    print(d)
    propose_id(d)
    print()

 

 

이제는 프로그래머스 문제 형식에 맞게 맞춰보겠습니다!

저는 각 단계를 구별하기 쉽게 새로운 변수를 썼지만, 하나만 사용해도 됩니다.

import re
def solution(new_id):
    # 1단계
    part1 =new_id.lower()
    # 2단계
    part2 = re.sub(r'[^\w\-.]', '', part1)
    # 3단계
    part3 = re.sub(r'[.]{2,}', '.', part2)
    # 4단계
    part4 = re.sub(r'^[.]|[.]?$', '', part3)
    # 5단계
    part5 = "a" if part4 == "" else part4
    # 6단계
    part6 = part5 if len(part5) <= 15 else re.sub(r'[.]$', '', part5[:15])
    # 7단계
    part7 = part6 if len(part6) >= 3 else part6 + part6[-1]*(3-len(part6))
    
    return part7

 

 

문제를 풀면서 났던 에러!

6단계에서 16자 이상이어서 문자열을 잘랐을 때 맨 마지막이 .인지 다시 봐야 한다!