Skip to content

🔗 คู่มือสำหรับการเพิ่ม แก้ไข กลุ่มทดสอบ แบบใหม่

Nepumi-Jr edited this page May 25, 2024 · 2 revisions

⚠️วิธีการเขียนรูปแบบเก่าที่ไม่ได้ใช้แล้ว

❓ กลุ่มทดสอบคืออะไร

กลุ่มทดสอบ(หรือ กลุ่มเทสเคส)คือการนำบททดสอบ (Test case)ต่าง ๆ มารวมกันออกเป็นกลุ่ม ๆ เพื่อที่จะสามารถปรับน้ำหนักหรือสร้างเงื่อนไขของแต่ละกลุ่มได้ เช่น โจทย์ข้อนี้มี 10 เทสเคส แล้วทำการแบ่งออกเป็นสามกลุ่ม กลุ่มแรกเป็น เทสเคส 1 2 กลุ่มที่สองเป็น 3 4 5 และกลุ่มสุดท้ายเป็น 6 7 8 9 และ 10 เป็นต้น

ในแต่ละกลุ่มจะสามารถตั้งค่าได้ดังนี้

  • เคส (ต้องมี) ก็คือกำหนดว่าในกลุ่มนี้จะนำบททดสอบไหนมาทดสอบไหนบ้าง ซึ่งสามารถกำหนดทั้งหมด 3 ลักษณะ

    1. คั่นด้วย ลูกน้ำ(Comma ,) ซึ่ง comma จะใช้คั่นระหว่างหมายเลขเคสต่าง เช่น 1, 2, 3, 7 นั้นคือ กลุ่มเคสนี้จะนำบททดสอบที่ 1 2 3 และ 7 มาใช้
    2. ใช้เครื่องหมายขีด ซึ่งจะใช้ในกรณีที่กลุ่มเคสนั้นมีบททดสอบที่เรียงติดกัน หรือเป็นช่วง ซึ่งสามารถเขียนได้โดยการเขียนตัวเลขสองตัว และคั่นด้วยตัวขีด เช่น 1-5 จะหมายถึงว่า กลุ่มเคสนี้ จะนำบททดสอบที่ 1 ถึง 5 มาใช้
    3. แบบผสม คือการนำแบบที่ 1 และแบบที่ 2 มาผสมกัน ซึ่งก็สามารถมองเครื่องหมาย comma ว่าเป็นการรวมกลุ่ม (union) ก็ได้ เช่น 1-3, 8-10, 12, 14-16 นั้นคือกลุ่มเคสนี้ จะนำบททดสอบที่ 1 2 3 8 9 10 12 14 15 และ 16 มาใช้ทดสอบ
  • น้ำหนัก ก็คือกำหนดน้ำหนักของกลุ่มนี้ ถ้าหากผู้ทำโจทย์สามารถผ่านทุก ๆ เทสเคสในกลุ่มนั้น ก็จะได้คะแนนเป็นไปตามน้ำหนักที่กำหนดไว้ หากผ่านแค่บางส่วน ก็จะได้คะแนนบางส่วนตามจำนวนเทสเคสและน้ำหนัก เช่นหากมีน้ำหนักเป็น 35 แล้วในกลุ่มนั้นมี 5 เทสเคสและผ่านแค่ 3 เทสเคสก็จะได้คะแนนเป็น 3/5×35 = 21 คะแนน เว้นแต่ในกรณีถัดมา

  • การมัดเทสเคส คือการกำหนดเงื่อนไขของการได้คะแนนของกลุ่มนั้น ๆ หากมีการมัดเคส(เป็นจริง) ผู้ทำโจทย์จะได้คะแนนเมื่อผ่านทุก ๆ เทสเคสของกลุ่มดังกล่าว หากไม่ผ่านแม้แต่หนึ่งเทสเคส ก็จะได้ 0 คะแนนจากกลุ่มเคสนั้น หากไม่มัดก็จะใช้การคำนวณปกติเหมือนเดิม

  • การกำหนด Requirement อย่างในบ้างข้อ อาจจะมีการแบ่งเป็นกลุ่มเทสเคสที่มีข้อมูลเล็ก ๆ และข้อมูลใหญ่ ๆ การที่ผู้ทำโจทย์ยังไม่ผ่านกับกลุ่มเล็ก ๆ มาก่อน ก็จะไม่ควรที่จะตรวจกับกลุ่มข้อมูลใหญ่ ๆ เช่นกัน ซึ่งผู้แต่งโจทย์ก็สามารถกำหนดว่า การที่จะตรวจกลุ่มนี้ จะต้องผ่านกลุ่มไหนมาก่อน หากผู้ส่งไม่ผ่านตามที่กำหนดไว้ ตัวตรวจจะทำการข้ามการตรวจกลุ่มนี้ทันที ซึ่งได้ผลตรวจเป็น S (Skip) และไม่ได้คะแนนในกลุ่มนั้น

  • การตั้งค่าการคำนวณ โดยทั่วไป การคำนวณในแต่ละ Subtask จะถูกคำนวณโดยการนำคะแนนในแต่ละเทสเคส มาเฉลี่ยกัน และคูณด้วยน้ำหนักของ Subtask นั้น ๆ และเมื่อคำนวณเสร็จแล้ว จะถูกคำนวณเป็นคะแนนรวมของโจทย์นั้น ๆ ซึ่งการตั้งค่านี้สามารถตั้งให้เปลี่ยนจากการนำคะแนนแต่ละเทสเคสมาเฉลี่ยกัน ไปเป็นการเอาคะแนนสูงสุดหรือต่ำสุดของ Subtask นั้น และคูณด้วยน้ำหนักของ Subtask นั้น ๆ ได้

แนะนำให้ดูตัวอย่างการคำนวณที่ท้ายเอกสารนี้

⚙ รูปแบบการตั้งค่า (ใหม่)

จะใช้รูปแบบ JSON ในการเก็บข้อมูลกลุ่มทดสอบ ซึ่งมีรูปแบบตัวอย่างดังต่อไปนี้

ในอนาคต อาจรองรับ YAML ได้ด้วย

{
  "version": 1.0,
  "data": {
    "subtask 1": {
      "case": "1-2",
      "group": false,
      "score": 30
    },
    "subtask 2": {
      "case": "3-5",
      "group": true,
      "score": 70,
      "require": 1
    },
    "subtask 3": {
      "case": "6-10",
      "group": false,
      "score": 70,
      "require": [1, 2]
    }
  }
}

จากตัวอย่างจะเห็นว่า ข้อมูลกลุ่มทดสอบต่าง ๆ จะอยู่ในข้อมูล data ซึ่งแต่ละ data ก็จะประกอบด้วย "subtask ?" ต่าง ๆ ตามที่เห็น และในแต่ละ subtask ก็จะประกอบด้วย

  • case (รับเป็น string) คือ การกำหนดว่ากลุ่มทดสอบนี้ จะใช้เทสเคสใดบ้าง (รับเป็น string) ซึ่งรูปแบบการเขียนคือ เป็นตัวเลขจำนวนเต็มบวกที่คั่นด้วย ขีด หรือ comma ตามที่ได้กล่าวข้างต้น ⚠️ต้องมีการกำหนด case ในทุกกลุ่มทดสอบ

  • score ใช้ข้อมูลเป็น จำนวนจริง คือ น้ำหนักคะแนนของกลุ่มทดสอบนั้น ๆ (มีค่าเริ่มต้นเป็น จำนวนเทสเคสในกลุ่มนั้น)

  • group ใช้ข้อมูลเป็น Boolean คือ การมัดกลุ่มทดสอบ (มีค่าเริ่มต้นเป็นจริง)

  • require ใช้ข้อมูลเป็นจำนวนเต็มบวก หรือเป็น list คือการกำหนด Requirement ของกลุ่มทดสอบนี้ (มีค่าเริ่มต้นเป็น [] ก็คือ ไม่มี)

  • option ใช้ข้อมูลเป็น string ของตัวเลือกดังนี้ sum|min|max คือการกำหนดว่าจะใช้การคำนวณคะแนนแบบไหน

    • sum คือการนำคะแนนทุกเทสเคสมาเฉลี่ยกันแล้วคูณด้วยน้ำหนัก
    • min คือการนำคะแนนที่น้อยที่สุดในกลุ่มนั้น ๆ มาคูณด้วยน้ำหนัก
    • max คือการนำคะแนนที่มากที่สุดในกลุ่มนั้น ๆ มาคูณด้วยน้ำหนัก

    ⚠️หมายเหตุ : ใช้ได้เมื่อไม่ได้มีการมัดกลุ่มทดสอบ (group : false) (มีค่าเริ่มต้นเป็น sum)

ตัวอย่าง

{
  "version": 1.0,
  "data": {
    "subtask 1": {
      "case": "1-2",
      "group": false,
      "score": 20
    },
    "subtask 2": {
      "case": "3-5",
      "group": true,
      "score": 30
    },
    "subtask 3": {
      "case": "6-8",
      "group": true,
      "score": 50,
      "require": 2
    },
    "subtask 4": {
      "case": "9-12",
      "group": true,
      "score": 50,
      "require": [1, 3]
    }
  }
}

สามารถอธิบายได้ภาพดังนี้...

ตัวอย่างภาพ

ผลตรวจก่อนการตรวจแบบกลุ่ม ผลตรวจหลังการตรวจแบบกลุ่ม คะแนน คำอธิบาย
PPPPPPPPPPPP (PP)[PPP][PPP][PPPP] 150 ถูกหมดอยู่แล้ว
PPPPPPPPPXP- (PP)[PPP][PPP][PXP-] 100 กลุ่มสุดท้ายดันมัดเคส ซึ่งก็จะไม่ได้คะแนนในส่วนนั้น
PPPPPPPPTXTT (PP)[PPP][PPP][TXTT] 100 แม้ว่าจะผิดมากหรือผิดน้อยในกลุ่มสุดท้าย ก็มีค่าเท่ากัน
PPPPPP-P???? (PP)[PPP][P-P][SSSS] 50 กลุ่มสามนั้นดันมัดเคส จึงทำให้ไม่ได้คะแนน และกลุ่มสุดท้าย ดันมีข้อกำหนดคือต้องผ่านกลุ่มสามก่อน ซึ่งทำให้กลุ่มสุดท้ายโดนข้ามบททดสอบ
PTPPPPPP???? (PT)[PPP][PPP][SSSS] 90 กลุ่มแรกผลาดแค่หนึ่งเทสเคส ซึ่งได้คะแนนเป็น 1/2×20=10คะแนน และเหมือนกันกับด้านบน ในกลุ่มสุดท้ายมีข้อกำหนดว่าต้องผ่านกลุ่มแรกก่อน จึงทำการข้ามบททดสอบ
PPP-P??????? (PP)[P-P][SSS][SSSS] 20 -
TT--P??????? (TT)[--P][SSS][SSSS] 0 -
XPPXT??????? (XP)[PXT][SSS][SSSS] 10 -

📃 การนำการตั้งค่ามาใส่ในโจทย์

ให้เอาข้อมูลดังกล่าว เก็บไว้ในไฟล์ที่ชื่อว่า subtask.json และนำไฟล์ได้แปะไว้ในแฟ้มเดียวกันกับ Testcase ของโจทย์ ตามตัวอย่างด้านล่างนี้

📁 ตัวอย่างโครงสร้างของไฟล์โจทย์

768 PPrime
 |- 1.in
 |- 1.sol
 |- 2.in
 |- 2.sol
 |- 3.in
 |- ...
 |- 14.sol
 |- subtask.json
 .

💯 ตัวอย่างการคำนวณคะแนน

ตัวอย่างการคำนวณจะเป็นตัวอย่างการตั้งค่า group และ option ในกรณีต่าง ๆ โดยจะสมมติให้มีเทสเคสอยู่ 4 เทสเคส และ มีน้ำหนักคะแนนเป็น 10

"subtask 1": {
  "case": "1-4",
  "score": 10
},

สถานการณ์ที่ 1 ในกรณีที่ถูกหมดอยู่แล้ว

Testcase 1 2 3 4
percent 100% 100% 100% 100%
การตั้งค่า สัญลักษณ์ผลตรวจ คะแนน คำอธิบาย
group : true [PPPP] 10 ถูกทุกกรณี จึงได้ 10 คะแนนตามน้ำหนัก
group : false (PPPP) 10 ถูกทุกกรณี จึงได้ 10 คะแนนตามน้ำหนัก

สถานการณ์ที่ 2 ในกรณีที่ผิดบางเคส

Testcase 1 2 3 4
percent 100% 100% 0% 100%
การตั้งค่า สัญลักษณ์ผลตรวจ คะแนน คำอธิบาย
group : true [PP-S] 0 เพราะผิด 1 เคส การตรวจจึงถือว่าผิดทั้งหมด (0 คะแนน)
group : false (PP-P) 7.5 เพราะถือว่าถูก 3 ใน 4 ซึ่งคิดเป็น 75% ซึ่ง 75% ของ 10 = 7.5 คะแนน
group : false, option: "min" (PP-P) 0 เพราะ min ของผลตรวจนี้คือ 0 (min ของ 100%, 100%, 0%, 100%) ซึ่งมีค่าเป็น 0
group : false, option: "max" (PP-P) 10 เพราะ max ของผลตรวจนี้คือ 100% (max ของ 100%, 100%, 0%, 100%) ซึ่งมีค่าเป็น 100% ของ 10 = 100

สถานการณ์ที่ 3 ในกรณีที่ผิดบางเคส + Partial

Testcase 1 2 3 4
percent 100% 70% 40% 20%
การตั้งค่า สัญลักษณ์ผลตรวจ คะแนน คำอธิบาย
group : true [P%SS] 0 แม้ว่าในเคสที่สองจะถูกเพียงบางส่วน แต่ก็ยังถือว่ายังไม่สมบูรณ์แบบ ซึ่งก็ถือว่าเป็น 0 คะแนนใน subtask นั้น
group : false (P%%%) 5.75 คำนวณได้จากเอา % มาเฉลี่ยกัน ซึ่งมีค่าเฉลี่ยเป็น 57.5% ซึ่งได้คะแนนเป็น 57.5% * 10
group : false, option: "min" (P%%%) 2 เพราะ min ของผลตรวจนี้คือ 20% ซึ่งมีค่าเป็น 20% * 10 = 2
group : false, option: "max" (P%%%) 10 เพราะ max ของผลตรวจนี้คือ 100% ซึ่งมีค่าเป็น 100% ของ 10 = 100

⚠ ข้อควรระวัง

หากไฟล์ subtask.json นั้นไม่ถูกไวยากรณ์ ไฟล์ subtask.json ดังกล่าวจะไม่ถูกใช้ และการตรวจจะเป็นไปตามเดิม (นั้นคือไม่มีการมัดเทสเคส)

⚠ หมายเหตุ

การมัดเทสอาจไม่มีผลต่อโหมดการแข่งขันบางโหมด เช่น codeforces(ACM) ที่หากไม่ผ่านแม้แต่เคสเดียว ก็จะทำให้ไม่ได้คะแนนในข้อนั้น

Clone this wiki locally