-
Couldn't load subscription status.
- Fork 1
🔗 คู่มือสำหรับการเพิ่ม แก้ไข กลุ่มทดสอบ แบบใหม่
กลุ่มทดสอบ(หรือ กลุ่มเทสเคส)คือการนำบททดสอบ (Test case)ต่าง ๆ มารวมกันออกเป็นกลุ่ม ๆ เพื่อที่จะสามารถปรับน้ำหนักหรือสร้างเงื่อนไขของแต่ละกลุ่มได้ เช่น โจทย์ข้อนี้มี 10 เทสเคส แล้วทำการแบ่งออกเป็นสามกลุ่ม กลุ่มแรกเป็น เทสเคส 1 2 กลุ่มที่สองเป็น 3 4 5 และกลุ่มสุดท้ายเป็น 6 7 8 9 และ 10 เป็นต้น
ในแต่ละกลุ่มจะสามารถตั้งค่าได้ดังนี้
-
เคส (ต้องมี) ก็คือกำหนดว่าในกลุ่มนี้จะนำบททดสอบไหนมาทดสอบไหนบ้าง ซึ่งสามารถกำหนดทั้งหมด 3 ลักษณะ
- คั่นด้วย ลูกน้ำ(Comma
,) ซึ่ง comma จะใช้คั่นระหว่างหมายเลขเคสต่าง เช่น1, 2, 3, 7นั้นคือ กลุ่มเคสนี้จะนำบททดสอบที่123และ7มาใช้ - ใช้เครื่องหมายขีด ซึ่งจะใช้ในกรณีที่กลุ่มเคสนั้นมีบททดสอบที่เรียงติดกัน หรือเป็นช่วง ซึ่งสามารถเขียนได้โดยการเขียนตัวเลขสองตัว และคั่นด้วยตัวขีด เช่น
1-5จะหมายถึงว่า กลุ่มเคสนี้ จะนำบททดสอบที่1ถึง5มาใช้ - แบบผสม คือการนำแบบที่ 1 และแบบที่ 2 มาผสมกัน ซึ่งก็สามารถมองเครื่องหมาย comma ว่าเป็นการรวมกลุ่ม (union) ก็ได้ เช่น
1-3, 8-10, 12, 14-16นั้นคือกลุ่มเคสนี้ จะนำบททดสอบที่1238910121415และ16มาใช้ทดสอบ
- คั่นด้วย ลูกน้ำ(Comma
-
น้ำหนัก ก็คือกำหนดน้ำหนักของกลุ่มนี้ ถ้าหากผู้ทำโจทย์สามารถผ่านทุก ๆ เทสเคสในกลุ่มนั้น ก็จะได้คะแนนเป็นไปตามน้ำหนักที่กำหนดไว้ หากผ่านแค่บางส่วน ก็จะได้คะแนนบางส่วนตามจำนวนเทสเคสและน้ำหนัก เช่นหากมีน้ำหนักเป็น
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
},| Testcase | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| percent | 100% | 100% | 100% | 100% |
| การตั้งค่า | สัญลักษณ์ผลตรวจ | คะแนน | คำอธิบาย |
|---|---|---|---|
group : true |
[PPPP] |
10 | ถูกทุกกรณี จึงได้ 10 คะแนนตามน้ำหนัก |
group : false |
(PPPP) |
10 | ถูกทุกกรณี จึงได้ 10 คะแนนตามน้ำหนัก |
| 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 |
| 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) ที่หากไม่ผ่านแม้แต่เคสเดียว ก็จะทำให้ไม่ได้คะแนนในข้อนั้น