第二次結對作業

chenoojkk發表於2024-10-10

一、結對成員

  • 031502332 汪志彬
  • 031502315 李芳凱

二、專案github地址

專案github地址

三、資料生成原理與考慮因素

  • 我們生成的一組資料:資料
    (為了能比較直觀,設定學生數為30,部門數為5;可通過修改程式碼引數,改變學生數量和部門數量)
  • 資料生成原理:
    • 學生資料:
      • 學號(student_no):按順序生成。以“031502”開頭,從“001”開始依次增大
      • 空閒時間(free_time):從週一到週日,通過隨機數(0或1)判斷當天是否產生空閒時間,產生則生成時間字串加入時間列表;為滿足空閒時間大於兩個,若最終生成的列表小於等於二,則重新生成
      • 申報部門(applications_department):先生成一個[1,5]之間的整數作為申請數量。然後隨機生成一個數字對應部門的數字編號(判斷是否重複生成,達到數量後退出)
      • 標籤(tags):將標籤設定為一個列舉型別,遍歷列舉物件,通過隨機數(0或1),判斷是否包含該標籤,若包含則加入該生標籤列表;若最終生成的列表小於等於二,則重新生成
    • 部門資料:
      • 部門號(department_no):按順序生成。以“D”開頭,從“01”開始依次增大
      • 活動時間(event_schedules):與學生空閒時間生成方式相同
      • 標籤(tags):與學生的標籤生成方式相同
      • 人數限制(member_limit):採用隨機數生成函式生成[10,15]之間的整數
  • 考慮因素:此生成程式最主要的特點是考慮到了部門的熱門程度(根據二八法則:%80的人選擇%20的部門)。將熱門的部門權重設定得大一點(實現方式是給比較熱門的部門分配比較多個的數字,eg:若有五個部門,生成隨機數字範圍設定為[1,15],部門1分配[1,8],部門2分配[9,11],依此),部門權重可通過修改程式碼進行設定。其它考慮的因素就是活動時間不能太早,最早從早上8點開始,最晚24點結束(好像還是有點晚)。

四、資料建模及匹配程式的思路及實現方式

  • 資料建模
    本次作業遇到的第一個難點就是如何從json格式的txt檔案中提取資料。最後通過搜尋發現有一個比較好用的的外部jar包(gson2.7),並學習了gson包的使用,有了這個工具讀取和輸出都顯得比較簡單了。資料組織方式和json中大體相似。如下
    • Department
      • department_no:部門編號
      • List event_schedules:部門活動時間,是一個String型別列表
      • List tags:部門標籤,是一個String型別列表
      • menber_limit:一個int型別,範圍在[10,15]之間的整數
      • isempty:bool型別,判斷部門是否為空
      • List member:是一個String型別的列表,儲存納入部門的學生學號
    • Student
      • student_no:學生編號
      • application_departments:所申請的部門列表,是一個String型別列表
      • List tags:學生標籤,是一個String型別列表
      • List free_time:部門標籤,是一個String型別列表
      • isadmitted:bool型別,判斷是否有被錄取
  • 匹配程式
    • 思路
      具體的思路比較簡單。站在部門的角度來選擇學生,即每個部門依次去遍歷學生列表,總共兩輪,第一輪只錄取沒被其它部門錄取的學生,第二輪則是符合要求即錄取原因如下:
      1、從頭到尾遍歷學生列表會對學號靠後的學生不公平,只錄取未被錄取的學生可以提高後面同學被錄取的機率(對後面的學生比較不公平)
      2、 部門正常也希望所錄取的部員所加入部門儘可能少,這樣才能在部門活動中投入較多時間

      • 第一次遍歷納新的步驟如下
        1.若該學生尚未加入任何部門,則執行下一步。否則選取下一位學生,執行1
        2.若學生的空閒時間是否與部門活動時間匹配,若有執行下一步。否則從學生列表裡選取下一位,執行1
        3.若學生有申請該部門,則執行下一步。否則從學生列表裡選取下一位,執行1
        4.若該生標籤與部門匹配,則納入該生。從學生列表裡選取下一位,執行1
      • 第二次遍歷納新步驟與第一次大體相同,但去除了步驟1,即第二輪符合條件即錄取,不管該生是否已加入部門
    • 實現方式
          // 開始匹配,由部門招人,分兩次,第一次招人優先招收未加入其它部門的人
          for (ExDepartment exdepartment : ed) {
              for (ExStudent exstudent : es) {
                  if(exstudent.isAdmitted())
                      continue;
                  if (isMatch(exdepartment, exstudent)) {
                      admitted(exdepartment, exstudent);
                  }
              }
          }
          //第二次招人,符合要求即招入
          for (ExDepartment exdepartment : ed) {
              for (ExStudent exstudent : es) {
                  if(exdepartment.getMembers().contains(exstudent))
                      continue;
                  if (isMatch(exdepartment, exstudent)) {
                      admitted(exdepartment, exstudent);
                  }
              }
      private static boolean isMatch(ExDepartment exdepartment, ExStudent exstudent) {
          // TODO Auto-generated method stub
          if (timematch(exdepartment, exstudent)) {
              for (String apt : exstudent.getApplication_department()) {
                  if (apt.equals(exdepartment.getDepartment_no())) {
                      return tagMatch(exdepartment, exstudent);
                  }
              }
          }
          return false;
      }

五、所遵循的程式碼規範(簡單舉例)

第二次結對作業

六、結果評估

  • 最終使用作業釋出部落格裡面的input_data.txt的檔案進行評測。
  • 評測結果:
    未被錄取學生數:109
    未錄取學生的部門數:0
  • 分析:最終獲得的結果是大部分學生都能找到部門加入,大部分部門都能錄取到一定的人數(10人以上),覺得應該算是錄取率比較高的一種演算法,主要優點也是能讓更多人蔘與到部門活動中取。但是這種演算法不足也非常明顯,主要有以下兩點
    • 對於學號靠後的學生較為不公平(雖然已經儘量避免)
    • 部門與學生之間的匹配較為寬鬆,即學生只要有填報該部門,至少符合有一個空閒時間與部門活動時間匹配,至少有一個標籤與部門標籤匹配,就有比較大可能被錄用。這可能會導致部門因為人數限制沒有錄取到更合適的人(匹配程度更高的人)。

七、心得體會

  • 個人收穫:通過這次的結對作業,我開始接觸Java包的使用,更加深刻地理解了Java的一些基礎知識。這次因為國慶放假,我和我的夥伴都回家了,所以也沒辦法坐在一起敲程式碼。程式碼主要是芳凱打的,只有結構佈局啊是我們一起構想的。感覺我這次沒有很參與到這次作業中,所以也沒有很大的收穫,但是沒辦法畢竟自己沒有投入很多時間。謝謝芳凱的辛勤!
  • 結對感受:芳凱是我同班同學,平時就是非常不錯的一個人!在結對作業的兩次合作中,他體現了他的知識水平和程式碼能力,特別想提的一點是,芳凱這人性格好!並沒有因為我水平比較不好而心存抱怨,反而是對於我不懂的地方悉心耐心地指導我,還告訴一些學習Java的途徑,謝謝他!

相關文章