[Programmers] 오픈채팅방 - Java

2021. 12. 23. 19:05Computer Sciences/Problem Solve

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

 

코딩테스트 연습 - 오픈채팅방

오픈채팅방 카카오톡 오픈채팅방에서는 친구가 아닌 사람들과 대화를 할 수 있는데, 본래 닉네임이 아닌 가상의 닉네임을 사용하여 채팅방에 들어갈 수 있다. 신입사원인 김크루는 카카오톡 오

programmers.co.kr

문제 설명

문제의 이해는 어렵지 않지만 간단하게 설명하면 다음과 같다.

방에 접속한 유저들은 uid로 구분되며 각 유저는 닉네임으로 구분된다. 그리고 명령어로는 Enter, Change, Leave가 있으며 Enter라면 입장 메시지가 출력되고 Leave라면 퇴장 메시지가 출력된다. 그리고 Change라면 해당 유저의 닉네임을 변경한다.

문제의 주요 내용은 최종적으로 보여지는 채팅방 접속 내역이다. 따라서 마지막으로 변경된 닉네임을 해당 유저의 닉네임으로 모두 사용하면 되는 것이다. 따라서 닉네임이 변경될 때마다 해당 uid를 가진 유저의 닉네임을 갱신하면 된다.

풀이 방법

필자는 HashMap을 이용하여 풀어냈다. HashMap은 같은 키가 저장되면 값을 덮어 쓰기 때문에 이 문제에 적합하다고 판단했다. 그리고 나중에 결과의 순서를 유지하기 위해 명령어를 commands, uid를 uids에 ArrayList로 저장했다. 그 이후에는 간단하다. 입력된 문자열을 파싱해서 commands, uids, userInfoPairs에 각각 저장한 후에 저장된 명령어에 따라 로그를 만들어낸 후 반환하면 끝난다.

입력 형식은 '명령어 uid 닉네임'으로 주어진다. Leave 일 때는 '명령어 uid'로 주어지므로 이 경우를 생각하자.

먼저 명령어, uid는 ArrayList로 저장한다. 그리고 uid와 매핑된 닉네임을 HashMap에 저장한다. HashMap에 저장하는 이유는 같은 키가 저장되는 경우 해당 키에 대한 값을 덮어쓰기 때문에 변경 처리를 따로 하지 않아도 시간의 흐름에 따라 가장 늦게 입력된 값이 저장된다. 

Enter 시에는 'Prodo님이 입장하셨습니다.' 라는 메시지가 저장된다. Leave 시에는 'Prodo님이 나갔습니다.' 라는 메시지가 저장된다. Change 시에는 닉네임이 변경되는데 이때는 닉네임만 변경하고 따로 메시지는 출력되지 않는다. 그리고 이 처리는 이미 입력받을 때 처리가 되었다. 자세한 코드는 아래에서 살펴보도록 하자.

코드

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

class Solution {
    
    private final static String messageWhenEntered = "님이 들어왔습니다.";
    private final static String messageWhenLeft = "님이 나갔습니다.";
    
    public String[] solution(String[] record) {
        /**
         * 입력받은 문자열 모두를 command, uid, nickname으로 구분
         * uid와 nickname은 map으로 저장시켜 놓음
         * 모든 명령어를 수행한 뒤에 명령어에 따라 로그 메시지를 출력한다.
         */
        ArrayList<String> commands = new ArrayList<>();
        ArrayList<String> uids = new ArrayList<>();
        Map<String, String> userInfoPairs = new HashMap<>();
        ArrayList<String> result = new ArrayList<>();
        
        for (String line : record) {
            String[] tokens = line.split(" ");
            commands.add(tokens[0]);
            uids.add(tokens[1]);
            
            // 배열 인덱스 예외 처리
            if (tokens[0].equals("Leave")) {
                continue;
            }
            // hashmap은 키가 똑같으면 덮어 쓴다
            userInfoPairs.put(tokens[1], tokens[2]);
        }
        
        for (int i = 0; i < commands.size(); i++) {
            String command = commands.get(i);
            switch (command) {
                case "Enter":
                    result.add(String.format("%s%s", userInfoPairs.get(uids.get(i)), messageWhenEntered));
                    break;
                case "Change":
                    break;
                case "Leave":
                    result.add(String.format("%s%s", userInfoPairs.get(uids.get(i)), messageWhenLeft));
                    break;
            }
        }
                               
        String[] answer = result.stream().toArray(String[]::new);
         
        return answer;
    }
}