본문 바로가기
코딩 테스트/프로그래머스

[프로그래머스 - Python] Lv.2 오픈채팅방

by 오엥?은 2023. 3. 12.
반응형
  • 문제

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

 

프로그래머스

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

programmers.co.kr

 

  • 풀이
def solution(record):
    # 1 (2차원 배열로 만들기)
    li = [list(x.split(' ')) for x in record]

    # 2
    name_dic = {}
    for x in range(0, len(li)):
        if (li[x][0] == 'Enter') | (li[x][0] == 'Change'):
            name_dic[li[x][1]] = li[x][2]

    # 3
    answer = []
    for x in range(0, len(li)):
        if li[x][0] == 'Enter':
            answer.append(f"{name_dic[li[x][1]]}님이 들어왔습니다.")
        elif li[x][0] == 'Leave':
            answer.append(f"{name_dic[li[x][1]]}님이 나갔습니다.")

    return answer

 

# 1

record가

["Enter uid1234 Muzi", "Enter uid4567 Prodo","Leave uid1234","Enter uid1234 Prodo","Change uid4567 Ryan"]

이런식으로 들어오니까 " "을 기준으로 나눠서 2차원 배열으로 만들었다. 

li = [list(x.split(' ')) for x in record]
# [['Enter', 'uid1234', 'Muzi'], ['Enter', 'uid4567', 'Prodo'], ['Leave', 'uid1234'], ['Enter', 'uid1234', 'Prodo'], ['Change', 'uid4567', 'Ryan']]

이렇게 나눠진다.

 

 

# 2

name = []
for x in range(0, len(li)):
    if li[x][0] == 'Enter':
        name.append([1, li[x][1], li[x][2]])
        for z in range(0, len(name)):
            if name[z][1] == li[x][1]:
                name[z][2] = li[x][2]
    elif li[x][0] == 'Leave':
        name.append([2, li[x][1], ''])
    elif li[x][0] == 'Change':
        for y in range(0, len(name)):
            if name[y][1] == li[x][1]:
                name[y][2] = li[x][2]

for x in range(0, len(name)):
    if name[x][2] == '':
        for y in range(0, len(name)):
            if name[x][1] == name[y][1]:
                name[x][2] = name[y][2]

처음엔 이랬다. name 배열 만들어서 Enter, Leave면 아이디와 닉네임을 append하고, Change면 name배열을 반복문 돌려서 같은 아이디를 찾아서 닉네임 바꿔버렸다. 근데 여기서 Enter 경우에는 나가서 닉네임을 바꾸고 들어오는 경우가 있어서 name 배열 반복문 돌려서 들어올 때마다 또 같은 아이디의 닉네임을 다 바꿨다. 또 li 에서 Leave 일 때는 닉네임이 담겨있지 않다. 그래서 큰 반복문을 빠져나간 뒤에 Leave (name[x][2] == '') 부분을 찾아서 아이디를 확인한 다음 name 반복문을 돌려서 같은 아이디 찾아서 그 닉네임으로 바꿨다. 이러면 코드 실행하면 성공은 하는데 시간초과다. 반복문 100개 있어서 그런 것 같다.

 

그래서 생각해 보니까 dictionary가 있었다. 나 진짜 왜 그랬지 

그래도 생각해낸 거 넘 행복해서 돌겠다.

name_dic = {}
for x in range(0, len(li)):
    if (li[x][0] == 'Enter') | (li[x][0] == 'Change'):
        name_dic[li[x][1]] = li[x][2]

dictionary key를 아이디로 하고 value를 닉네임으로 하면 li 배열 반복문 돌리면서 닉네임 알아서 바꿔준다. 

Enter의 경우는 유저가 나갔다가 닉네임을 바꾸고 다시 들어오는 경우가 있다. Change는 나가지 않고 닉네임을 바꾸는 거다. 그러니까 두 경우 모두 맨 마지막의 닉네임이 최종 닉네임이 되는 거다. 

li 반복문을 돌리면서 Enter와 Change의 경우에만 name_dic[li[x][1]] = li[x][2] 을 하면 

name_dic = {'uid1234': 'Prodo', 'uid4567': 'Ryan'} 이 된다.

 

 

# 3

["Prodo님이 들어왔습니다.", "Ryan님이 들어왔습니다.", "Prodo님이 나갔습니다.", "Prodo님이 들어왔습니다."]  

 

출력은 위와 같이 되어야 한다.  들어오고 나간 건 표시되지만, 닉네임이 바뀐 것은 표시되지 않는다. 그리고 닉네임이 Muzi 인 상태에서 들어왔더라도, Prodo 로 바꿔버리면 'Muzi 님이 들어왔습니다.' 가 'Prodo님이 들어왔습니다.' 로 바뀌어야 한다.

 

그래서 딕셔너리에 저장된 닉네임값, 즉 name_dic 의 value를 사용하면 된다. value 값 가져오는 방법은 name_dic['key'] 로 가져오면 된다. li[x][0] == Enter 일 때는 만들어 둔 빈 배열 answer에 f"{name_dic[li[x][1]]}님이 들어왔습니다." 을 append 한다. 그러면 li 에서 가져온 아이디로 현재의 닉네임값을 불러올 수 있다. 반대로 Leave 일 때는 f"{name_dic[li[x][1]]}님이 나갔습니다." 을 append 하면 된다.

 

 

반응형