オープンチャットルーム


中に入ると


2019年のKACABLINDで初めてのCOTEEの問題です.今回も文字列グループについて質問です.公開チャットルームのヒントに返信します.このとき重要なのはプレイヤーのニックネームです.ニックネームの変更には、チャットルームを離れることと、チャットルームでニックネームを変更することの2種類があります.このときニックネームは繰り返すことができます.
見た瞬間に地図を書こうと思えばよかった.mapのkeyは重複できないので、idをkeyに入れてニックネームが変わるたびにIDの変更をvalueとして入れればいいのではないでしょうか.しかし、ここで少し問題があったのは、二重ドアを2回回すことだ.idとnameのデュアルfor文を保存し、メッセージを実際に格納するデュアルfor文.
でも、それ以上に大きな悩みが...それは文字列グループです.ユーザの入力,離脱,変更のヒントは文章からなるため,3つの要素に分けられる.プレイヤーの行動、プレイヤーのid、プレイヤーのニックネーム.優雅なトランポリン(Stringstreamか...)があるに違いないが、スペースの位置を直接検索しsubstr()を使用する方法を使用しました.結果は解けた.エレガントさが落ちるかもしれないけど….

コードの説明


まずmapを用いてidとnameを取得する.二重for文を使用して、最初のfor文で1つの文を2回測定し、文の中で1つの文の文字を1つずつチェックします.したがって,スペースが現れるとblankに++を加えることで,スペースの前後の位置がわかる.blankが1であれば、前に動作があり、後ろにidがあり、blankが2であれば、前にidがあり、後ろにnameがあることを表す.
次の動作が「Leave」でない場合にのみ、文字列をmapに分割します(「Leave」の場合、スペースが1つしかないので問題が発生します).id lはidの長さを表し、namelはnameの長さを表す(ここでは1を減算して正しい長さを得る).idをfirstからid l-1の長さに、nameをsecondからnamelの長さに入れます.次に作成するマッピングid nameでは、idをキーとしてnameをvalueとします.これでネット名を変えても自動的に変更されます.mapのキーは重複する値を入力できないためです.
次は答えに情報を入れる操作です.blankを探す方法は上の二重for文と同じでいいです.動作が「Enter」の場合、id nameでidを検索し、存在する場合はtmpに対応するvalue nameを追加し、後の文を追加します.そして,生成したtmpを応答に入れればよい.「Leave」もそうです.ただし、「Leave」ではidの長さはr.length()−firstである.「Leave」にはスペースが1つしかないのでidが同じ場合、対応するidの値をtmpに追加し、必要な文を追加します.そして答えを押すと「Leave」も完成
最後に出した答えを逆さまにして本当に終わりました!ああ...行間stringstreamを熟知し、より優雅なコードを書く必要があります.

コード#コード#

#include <string>
#include <vector>
#include <map>
#include <iostream>

using namespace std;

vector<string> solution(vector<string> record) {
    vector<string> answer;
    map<string, string> id_name;
    
    for(auto r : record){
        int blank = 0;
        int first = 0;
        int second = 0;
        
        for(int i=0; i<r.length(); i++){
            if(r[i] == ' '){
                blank++;
                if(blank == 1){
                    first = i+1;
                }
                if(blank == 2){
                    second = i+1;
                }
            }
        }           
            if(r.substr(0, first-1) != "Leave"){
                int id_l = second - first;
                int name_l = r.length() - second;
                string id = r.substr(first, id_l-1);
                string name = r.substr(second, name_l);
                id_name[id] = name;
            }
    }
    
    for(auto r : record){
        int blank = 0;
        int first = 0;
        int second = 0;
        string tmp = "";
        
        for(int i=0; i<r.length(); i++){
            if(r[i] == ' '){
                blank++;
                if(blank == 1){
                    first = i+1;
                }
                if(blank == 2){
                    second = i+1;
                }
            }
        }
        if(r.substr(0, first-1) == "Enter"){
            int id_l = second - first;
            string id = r.substr(first, id_l-1);
            auto name = id_name.find(id);
            if(name != id_name.end()){
                tmp += name->second;
            }
            tmp += "님이 들어왔습니다.";
            answer.push_back(tmp);
        }
        
        if(r.substr(0, first-1) == "Leave"){
            int id_l = r.length() - first;
            string id = r.substr(first, id_l);
            auto name = id_name.find(id);
            if(name != id_name.end()){
                tmp += name->second;
            }
            tmp += "님이 나갔습니다.";
            answer.push_back(tmp);
        }
    }

    return answer;
}