300x250

1. 제목

- 프로그래머스(17686) : 2018 KAKAO BLIND RECRUITMENT 오픈채팅방

문제 링크 : 코딩테스트 연습 - 오픈채팅방 | 프로그래머스 스쿨 (programmers.co.kr)

 


2. 풀이 과정

 

uidMap이라는 map 자료구조는 유저 아이디를 key로, 유저의 닉네임을 value로 저장합니다. uidRecord라는 벡터는 각 로그마다 유저 아이디와 해당 로그 메시지를 pair로 묶어 저장하는 용도로 사용됩니다.

for 루프에서는 record 벡터의 각 로그를 분리하여 command, uid, nickname 변수에 저장합니다. command 변수는 로그 유형을, uid 변수는 유저 아이디를, nickname 변수는 유저의 닉네임을 나타냅니다.

로그 유형에 따라 다음과 같은 처리를 수행합니다.

Enter: uidMap에 해당 유저 아이디가 이미 존재하는 경우에는 닉네임을 업데이트하고, 존재하지 않는 경우에는 새로 추가합니다. 그리고 uidRecord 벡터에 유저 아이디와 "님이 들어왔습니다."라는 메시지를 pair로 묶어 추가합니다.
Leave: uidRecord 벡터에 유저 아이디와 "님이 나갔습니다."라는 메시지를 pair로 묶어 추가합니다.
Change: uidMap에 해당 유저 아이디가 존재하는 경우에는 닉네임을 업데이트합니다.
uidRecord 벡터에 추가된 pair들은 마지막 for 루프에서 uidMap을 참조하여 출력 문자열을 생성하고, answer 벡터에 추가됩니다.


코드를 자세히 살펴보면, 우선 record라는 vector<string>을 입력값으로 받아들입니다. 이 record는 각 로그를 문자열 형태로 저장하고 있습니다. 이후 uidMap이라는 map 자료구조와 uidRecord라는 vector<pair> 자료구조를 선언해줍니다.

이후 record의 크기만큼 반복문을 실행하면서, split 함수를 이용하여 로그를 공백 단위로 분리해줍니다. 이 분리된 로그를 기반으로 각 로그에 따른 처리를 해줍니다.

만약 Enter 명령어가 들어온다면, 해당 유저가 기존에 존재하는 유저인지 신규 유저인지를 판단하여 uidMap에 저장합니다. 또한, uidRecord에는 해당 유저가 들어왔음을 기록해줍니다.

만약 Leave 명령어가 들어온다면, 해당 유저가 나갔음을 uidRecord에 기록해줍니다.

만약 Change 명령어가 들어온다면, uidMap에 해당 유저의 닉네임을 변경해줍니다.

이렇게 각 로그에 대한 처리를 마친 후, uidRecord에 저장된 로그 정보와 uidMap에 저장된 유저 정보를 기반으로 최종적인 출력 값을 만들어냅니다. uidRecord의 크기만큼 반복문을 실행하면서, uidMap에서 해당 유저의 닉네임을 가져와 로그와 함께 출력 값을 만들어 answer vector에 push_back 해줍니다.

 

 


3. 코드

#include <string>
#include <vector>
#include <map>
#include <sstream>

using namespace std;

//https://www.lifencoding.com/language/22#post?p=1
vector<string> split(string str, char Delimiter) 
{
    istringstream iss(str);             // istringstream에 str을 담는다.
    string buffer;                      // 구분자를 기준으로 절삭된 문자열이 담겨지는 버퍼

    vector<string> result;

    // istringstream은 istream을 상속받으므로 getline을 사용할 수 있다.
    while (getline(iss, buffer, Delimiter)) 
    {
        result.push_back(buffer);               // 절삭된 문자열을 vector에 저장
    }

    return result;
}

vector<string> solution(vector<string> record) 
{
    vector<string> answer;

    map<string, string> uidMap;
    vector<pair<string, string>> uidRecord;

    int recordSize = record.size();
    for (int i = 0; i < recordSize; i++)
    {
        vector<string> splitStr = split(record[i], ' ');
        string command = splitStr[0];
        string uid = splitStr[1]; 
        
        if (command == "Enter")
        {
            string nickname = splitStr[2];
            // 기존 유저
            if (uidMap.find(uid) != uidMap.end())
                uidMap[uid] = nickname;
            // 신규 유저
            else
                uidMap.insert({uid, nickname});

            uidRecord.push_back({uid, "님이 들어왔습니다."});
        }
        else if (command == "Leave")
        {
            uidRecord.push_back({ uid, "님이 나갔습니다." });
        }
        else if (command == "Change")
        {
            string nickname = splitStr[2];
            if (uidMap.find(uid) != uidMap.end())
                uidMap[uid] = nickname;
        }
    }

    int uidRecordSize = uidRecord.size();
    for (int i = 0; i < uidRecordSize; i++)
    {
        answer.push_back(uidMap[uidRecord[i].first] + uidRecord[i].second);
    }

    return answer;
}
300x250