[Programmers][Py] 신규 아이디 추천

mj·2024년 7월 17일
0

코딩테스트문제

목록 보기
37/50

✅ 문제


문제 바로가기

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이 될 때까지 반복해서 끝에 붙입니다.
  1. 소문자로 바꾸기
  2. 허용되지 않는 문자 제거하기
  3. 연속 마침표(...) -> 한개로(.) 만들기
  4. 처음 또는 끝에 위치한 마침표 제거하기
  5. 빈 문자열이면 'a'대입
  6. 길이 16이상이면 15개까지만, 그 이상은 제거
    마침표가 끝에 위치하면 제거
  7. 길이가 2자 이하이면, 마지막 문자를 길이가 3이 될 때까지 늘리기



✅ 나의 풀이


▶️ 1단계

소문자로 바꾸기

id = id.lower()

▶️ 2단계

허용되지 않는 문자 제거하기
📢 아이디는 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용할 수 있다.

for s in id:
        if not (s.islower() or s.isdigit() or s in ['-', '_', '.']):
            id = id.replace(s, "")

▶️ 3단계

연속 마침표 제거하기

첫번째 떠올린 방법

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

맨 처음에는 문자열에 ..이 없을때까지 while로 반복하며 ...로 바꿔주는 방법을 생각했다. 그러나, 최악의 경우(ex. 모든 문자가 .이고 길이가 1000인 문자열) while문은 1000번 실행이 된다. 또, 이때마다 문자열에 ..이 있는지 찾는 in의 시간복잡도 O(n)이 더해지므로 시간이 많이 걸릴것이라 생각했다. 반면 아래처럼 for문을 사용하면 최악의 경우에도 1000번만 실행되므로 아래의 방법을 선택했다.

최종 선택한 방법

# 3
new_id = id[0]
for i in range(1, len(id)):
    if not (id[i] == id[i-1] == '.'):
        new_id += id[i]

문자열의 2번째부터 탐색을 시작한다. 만약 현재위치의 문자와 앞의 문자가 .이면 마침표가 연속된다는 뜻이다. 따라서 마침표가 연속되지 않는 경우에만 현재문자를 새로운 문자열에 추가한다.

▶️ 4단계

처음 또는 끝에 위치한 마침표 제거하기

# 4
if new_id and new_id[0] == '.': new_id = new_id[1:]
if new_id and new_id[-1] == '.': new_id = new_id[:-1]    

빈 문자열인 경우 if문을 실행할수없도록 and조건을 넣어 구현하여야 한다.

IndexError

빈 문자열 ''의 경우 첫번째 if문에서 error가 발생하고, 문자열 '.'은 두번째 if문에서 error가 발생한다.
빈 문자열에 대해 인덱스로 접근하면IndexError: string index out of range 에러가 발생한다.

▶️ 5단계

빈 문자열이면 'a'대입

# 5
if not new_id: new_id = 'a'

▶️ 6단계

길이 16이상이면 15개까지만, 그 이상은 제거
마침표가 끝에 위치하면 제거

# 6
if len(new_id) >= 16: new_id = new_id[0:15]
if new_id[-1] == '.': new_id = new_id[:-1]  

▶️ 7단계

길이가 2자 이하이면, 마지막 문자를 길이가 3이 될 때까지 늘리기

# 7
if len(new_id) <= 2: new_id += new_id[-1] * (3-len(new_id))  

✅ 전체 코드


def solution(id):
    # 1
    id = id.lower()

    # 2
    for s in id:
        if not (s.islower() or s.isdigit() or s in ['-', '_', '.']):
            id = id.replace(s, "")

    # 3
    new_id = id[0]
    for i in range(1, len(id)):
        if not (id[i] == id[i-1] == '.'):
            new_id += id[i]

    # 4
    if new_id and new_id[0] == '.': new_id = new_id[1:]
    if new_id and new_id[-1] == '.': new_id = new_id[:-1]

    # 5
    if not new_id: new_id = 'a'

    # 6
    if len(new_id) >= 16: new_id = new_id[0:15]
    if new_id[-1] == '.': new_id = new_id[:-1]
    
    # 7
    if len(new_id) <= 2: new_id += new_id[-1] * (3-len(new_id))
    
    return new_id




Comment

어떻게 구현하면 되는지를 문제에서 7단계로 자세히 알려주었기 때문에 간단한 문제라고 생각했지만 아니였다. 문자열이나 함수를 잘 다룰수 있어야 하고 놓치기 쉬운 예외를 찾아 처리할 수 있어야 했다. 여러군데에서 실수가 있어서 고치느라 오래걸렸다ㅜ 코드로 구현해내는것이 어려웠던 문제...

profile
일단 할 수 있는걸 하자.

0개의 댓글