結對第二次做業





結對成員




周琪文 031502642
張旗 031502243





git

Github連接




點擊這裏進入github



github

最「好」數據&原理以及所考慮的因素(張旗)


最「好」數據


github的BIN目錄中哦
算法


"數據生成"程序的原理以及所考慮的因素


生成原理


這裏以生成部門標籤爲例,先構建一個存放全部標籤的數組tags[9],存放"film", "English", "reading", "music", "dance", "basketball", "chess",部門隨機生成2~5(tags_cnt = rand() % 4 + 2)個標籤(需考慮去重),在for循環中隨機生成tags_num = rand() % 10(去重),就是部門標籤,以此類推。
編程




考慮因素

  1. freetime 生成時間有兩種,考慮到上課時間衝突,常規上課時間少生成一點,非上課時間多生成一點,時長都是兩個小時。
  2. 標籤隨意生成 2-5個隨機,不重複,從總的標籤集合(數組)中取。
  3. 意向部門0-5個隨機,不重複,意向部門編號從總的集合(數組)中取。
  4. 部門收的人數個數memberlimit在8-16個。
  5. 生成有空時間沒有個數限制,生成時的規律是必定機率(上課時間爲20%,非上課時間爲80%)向下生成,連續生成的機率減小10%到40%。 一天二十四個小時分紅12個時間片,七天生成84個片生成空閒時間片。
  6. 學號按照必定規則排列,以咱們學院爲主(031502xxx),不重複。






數據建模及匹配程序的思路及實現方式(周琪文所作)



提供輸入包括:
20個部門
部門編號(惟一肯定值),字符;
各部門須要學生數的要求的上限,單個,數值,在[10,15]內;
各部門的特色標籤,多個(兩個以上),字符;
各部門的常規活動時間段,多個(兩個以上),字符。
300個學生
學生編號(惟一肯定值),字符;
學生空閒時間段,多個(兩個以上),字符;
興趣標籤,多個(兩個以上),字符(學生的興趣標籤必定是全部部門特色標籤其中的一個)
每一個學生有很少於5個的部門意願(助教測試時測試數據中部門意願可能會出現空缺,非空缺的部分必定是部門編號中的一個,並按照優先級從高到底的順序排序)。
實現一個智能自動分配算法,根據輸入信息,輸出部門和學生間的匹配信息(一個學生能夠確認多個他所申請的部門,一個部門能夠分配少於等於其要求的學生數的學生) 及 未被分配到學生的部門 和 未被部門選中的學生。
數組



建模:使用不定長向量vector。先讀取文件,把文件轉化成數組形式,每個同窗用同一個下標表示,並封裝。
數據結構


vector<vector<string>> studentsTime; //學生空閒時間
vector<vector<string>> studentsApp; //學生的申請部門
vector<vector<string>> studentsID; //學生學號
vector<vector<string>> studentsTags; //學生興趣標籤

vector<vector<string>> deptNo; //部門編號
vector<vector<string>> deptTags; // 部門標籤
vector<vector<string>> deptEvent; //部門常規時間
vector<vector<int>> deptMumLimit; //部門人數限制



建三張搜索表,分別是:
app

  • 標籤到部門下標的字典。
  • 時間到部門下標的字典。
  • 部門No到部門下標的字典。


例如,標籤到部門下標的字典( map < string,set < int > > ):
函數

  • map中string 是特徵標籤。
  • set是集合,存包含標籤的部門的下標,用整型表示。

tags 含有該tag的部門
film 實踐外聯部
dance 文化部
basketball 體育部



在匹配時,取出學生的標籤對應的部門集合,和學生申請的部門集合,進行交運算,獲得set1,再把set1,和空閒時間對應的部門集合進行交運算,獲得最後的集合。
測試


找到符合我的興趣和時間的集合後,再檢查是否已加入,重複,沒法加入(已加入五個部門),部門已達到人數上限等問題。
優化


具體代碼


讀取文件並存儲


/*讀入部門數據,並存儲*/
    for (int i = 0; jv["departments"][i].asBool(); i++)
    {
        //ID
        vector<string> tID;
        tID.push_back(jv["departments"][i]["department_no"].asString());  //讀入部門號並放入vector中
        dict_no2index.insert(pair<string, int>(jv["departments"][i]["department_no"].asString(), i));//將vector放入容器中,造成二維數字

        //一樣的方法讀入時間段,標籤,和人數限制,一樣用vector組成的二維數組保存起來
        deptNo.push_back(tID);
        //time
        vector<string> tTime;
        for (int j = 0; jv["departments"][i]["event_schedules"][j].asBool(); j++)
        {
            //string ss = "\"" + jv["departments"][i]["event_schedules"][j].asString() + "\"";
            tTime.push_back(jv["departments"][i]["event_schedules"][j].asString());
        }
        deptEvent.push_back(tTime);

        //tags
        vector<string> tTags;
        for (int j = 0; jv["departments"][i]["tags"][j].asBool(); j++)
        {
            tTags.push_back(jv["departments"][i]["tags"][j].asString());
        }
        deptTags.push_back(tTags);

        /[表情]mit
        vector<int> tLimit;
        tLimit.push_back(jv["departments"][i]["member_limit"].asInt());
        deptMumLimit.push_back(tLimit);
    }


構造字典


map<string, set<int>> dict_time;  //建造時間段->部門下標的字典
    for(int i = 0;i < deptEvent.size();i++)  //遍歷部門
    {
        for(int j = 0;j < deptEvent[i].size();j++)  //遍歷部門的時間段
        {
            if(dict_time.count(deptEvent[i][j]) == 0)  //若是時間段沒有在這個字典中
            {
                set<int> frees;  //添加字典項
                frees.insert(i);
                dict_time.insert(pair<string, set<int>>(deptEvent[i][j],frees));
            }
            else
            {
                dict_time[deptEvent[i][j]].insert(i);  //若是時間段已存在,就添加到對應的集合中
            }
        }
    }


利用集合的交運算進行匹配(截取標籤匹配的部門代碼,說明程序匹配的原理)


for (int i = 0; i < studentsID.size(); i++) //取出一個學生
    {
        set<int> apps;
        set<int> apps2;
        for (int j = 0; j < studentsApp[i].size(); j++)  //得到該學生的意向部門集合
        {
            //cout << studentsApp[i][j] << " ";
            //cout << dict_no2index[studentsApp[i][j]] << " " << endl;
            apps.insert(dict_no2index[studentsApp[i][j]]);
        }
        for (int j = 0; j < studentsTags[i].size(); j++) //進行標籤匹配,取出學生的一個標籤
        {
            set<int>::iterator it;
            set<int> tags = dict_tags[studentsTags[i][j]]; //根據字典找到該標籤對應的社團集合
            /*cout << "tags ";
            for (it = tags.begin(); it != tags.end(); it++)
            {
                cout << *it << " ";
            }
            cout << endl;
            cout << "apps ";
            for (it = apps.begin(); it != apps.end(); it++)
            {
                cout << *it << " ";
            }
            cout << endl;*/
            set<int>::iterator it1;
            set<int>::iterator it2;

            for (it1 = apps.begin(); it1 != apps.end(); it1++)  //進行循環,完成集合交運算
            {
                bool remove = true;;
                for (it2 = tags.begin(); it2 != tags.end(); it2++)
                {
                    if (*it1 == *it2)
                    {
                        remove = false;
                        break;
                    }
                }
                if (!remove)
                {
                    apps2.insert(*it1);
                }
            }






代碼規範



  1. 使用空行來分割邏輯,易於解讀。
  2. 使用註釋和花括號——上下對齊式。
  3. 不使用的代碼暫且註釋,由於工程不大,因此這裏先註釋掉,而且註明註釋緣由。若項目龐大,則考慮使用git,來保存舊版本,便於回滾。
  4. 不用中文拼音作變量名。字段名所有使用中文拼音縮寫,使人費解,並且很是彆扭。對變量賦予實際英語意義,便於理解。






結果評估



根據匹配的結果,對本身生成的數據,沒有學生匹配到的個數在10個左右,通常沒有部門收不到人。
對這樣的結果不太滿意具體以下:

  1. 在匹配時對我的之間的優先級沒有進行約束,是先到先進。
  2. 在針對時間匹配上的處理須要優化,例如,針對部門時間14:00~16:00,我的空閒時間14:00~17:00並不會匹配。
  3. 在數據結構上,對數據的匹配速度上還不是很滿意。


問題出在處理的規則太簡單,目前想到的解決方法與優化爲:

  1. 能夠將第一個填寫的志願部門做爲第一志願,優先級最高,以此類推,可是因爲水平與時間有限,會在之後完善。
  2. 能夠將數字進行大小比較,目前在程序中還未實現,會在之後完善。
  3. 程序還須要進一步優化。
  4. 還須要學會用github回退到之前版本,這樣能夠減小大量冗餘註釋。






結對感覺


主要的分工是:張旗負責生成函數,周琪文負責匹配。


在結對編程的體驗中,感受到和以前我的編程最大的不一樣就是對於編程要求的衝突,這個要求是各個方面的,好比說編程的進度,對項目的不一樣理解,匹配的規則的處理等,在我的編程中,全部的事情雖然是一我的作,雖然繁瑣,可是自由,可是在結對項目中,雖然兩我的比一我的的編程能完成更大的工做量,可是也可能由於衝突而致使進度的滯後,(終於知道了爲何老師說不要和本身熟悉的人合做了)。

結對的好處顯而易見,就是能作到並行的開發,加快了項目的進度,可是這樣作也帶來一些問題,就是在最開始兩我的沒有對項目的細節有同一的認識的話,到了項目整合階段,會付出巨大的時間和精力去和對方進行協調,反而不如一我的編程來得快。所以在項目開始階段就要作好溝通,針對本次合做,作好生成程序和匹配程序的銜接。

溝通!溝通!溝通!若是兩我的沒有一個同一的認識,只會事倍功半! 在結對編程的過程當中,耐性也相當重要。在編程過程當中,遇到bug是常有的事,若是這時變得煩躁而使得兩我的之間出現了隔閡,不只是影響了溝通,進而下降了項目的質量,並且這樣的合做最終必定會以不愉快結束。

相關文章
相關標籤/搜索