结对第二次做业





结对成员




周琪文 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是常有的事,若是这时变得烦躁而使得两我的之间出现了隔阂,不只是影响了沟通,进而下降了项目的质量,并且这样的合做最终必定会以不愉快结束。

相关文章
相关标签/搜索