https://wiki.tfcis.org/api.php?action=feedcontributions&user=Xiplus&feedformat=atom
TFcisWiki - 使用者貢獻 [zh-tw]
2024-03-29T15:16:31Z
使用者貢獻
MediaWiki 1.39.2
https://wiki.tfcis.org/index.php?title=MediaWiki:Loginprompt&diff=454
MediaWiki:Loginprompt
2024-02-15T12:45:32Z
<p>Xiplus:</p>
<hr />
<div>{{int:Signupstart}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=MediaWiki:Signupstart&diff=453
MediaWiki:Signupstart
2024-02-15T12:45:00Z
<p>Xiplus:建立新頁面</p>
<hr />
<div>'''註冊後,需請另一位已認證的使用者授予相同權限才可編輯。'''</div>
Xiplus
https://wiki.tfcis.org/index.php?title=MediaWiki:Loginprompt&diff=414
MediaWiki:Loginprompt
2022-10-20T01:28:14Z
<p>Xiplus:</p>
<hr />
<div>'''若為資訊社社員,可以請已有帳號的社員協助註冊,或在資訊社Facebook社團申請帳號。'''</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS%E5%92%8CCMS%E8%88%87%E5%8E%9F%E7%89%88%E5%B7%AE%E7%95%B0&diff=413
TPS和CMS與原版差異
2022-09-15T03:29:08Z
<p>Xiplus:/* CMS */</p>
<hr />
<div>為了讓[[TPS]]更貼近資訊社的使用狀況,對於原版的程式碼有做出若干修改。<br />
<br />
== [[TPS]] ==<br />
[https://github.com/TNFSH-Programming-Contest/TPS-example/tree/2af5e6dbdbcb251458532b399a7bc53c54b7187a TNFSH-Programming-Contest/TPS-example](2020/9/13)是基於[https://github.com/ioi-2017/tps/tree/7ca3cce28e25376a6992459c810abc3f6385d035 ioi-2017/tps](2020/8/31、scripts version 1.19)的修改。<br />
<br />
* [https://github.com/TNFSH-Programming-Contest/TPS-example/blob/2af5e6dbdbcb251458532b399a7bc53c54b7187a/Arithmetic/scripts/internal/parseSubtask.py scripts/internal/parseSubtask.py]:將subtasks.json轉換成pandoc能讀取的格式(subtask-pandoc.json)。<br />
* [https://github.com/TNFSH-Programming-Contest/TPS-example/blob/2af5e6dbdbcb251458532b399a7bc53c54b7187a/Arithmetic/scripts/verify.py#L195 scripts/verify.py]:修正solution資料夾不存在會出錯的問題。<br />
* [https://github.com/TNFSH-Programming-Contest/TPS-example/blob/2af5e6dbdbcb251458532b399a7bc53c54b7187a/Arithmetic/scripts/statement.sh scripts/statement.sh]:產生題本的script。<br />
=== problem.json ===<br />
[https://github.com/TNFSH-Programming-Contest/TPS-example/blob/2af5e6dbdbcb251458532b399a7bc53c54b7187a/Arithmetic/problem.json problem.json]。<br />
* 增加contest_name,為競賽名稱。<br />
* 增加problem_label,題本編號(A, B, C...)<br />
* 增加score_mode,評分賽制(IOI 2017-)<br />
* 增加feedback_level<br />
* 增加ignore_checker,匯入至CMS時忽略checker<br />
* 增加ignore_datasets,不匯入測資<br />
<br />
== [[CMS]] ==<br />
[https://github.com/TFcis/cms/tree/73bd95393d201bdf0d28de96890902527dc2b4b8 TFcis/cms](2021/9/18)是基於[https://github.com/cms-dev/cms/tree/e56ab0a932d7e2f0c10a3263310bb4c794fc85bf cms-dev/cms 1.4.rc1](2018/11/2)的修改([https://github.com/tfcis/cms/compare/e56ab0a932d7e2f0c10a3263310bb4c794fc85bf...73bd95393d201bdf0d28de96890902527dc2b4b8 compare])<br />
* 如果TPS有設定problem_label,則title前綴加上problem_label。<br />
* 題本資料夾從statements改成statement(CMS的bug)。<br />
* 如果不匯入statements(get_statement),那麼也不匯入attachments。<br />
* 增加feedback_level<br />
* 多項limit的預設值修正<br />
* 增加score_mode<br />
* 增加ignore_datasets,不匯入測資<br />
* 修正subtasks.json解析(CMS的bug)。<br />
* subtasks可以從mapping檔產生或是在subtasks.json設定regex。<br />
* 移除TPS code欄位。<br />
* 增加checker.py。<br />
* 在前端不對題目名稱強制轉成大寫。<br />
* 增加C++14、C++17。</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=412
題目敘述故事
2022-09-07T07:42:43Z
<p>Xiplus:/* 插圖 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 包裝程度比較 ==<br />
{{TOJ side box|570|E. 存在X}}<br />
以下使用的範例為 {{TOJ|570}}(109 學年度資訊學科能⼒競賽臺南⼀中校內複選,E. 存在X)在準備競賽時題目敘述演進過程的真實案例。<br />
<br />
=== Level 1 ===<br />
{{Quote|<br />
問是否可以以 <math>1 \times 2</math> 骨牌組成給定的遞增圖形。<br />
}}<br />
由出題者寫出來最原始的題目敘述,通常還需要額外的口頭補充解釋才能讓其他人理解題目,這樣的敘述僅能夠讓命題團隊的其他成員記得題目內容,但不足以在正式競賽中使用。<br />
<br />
=== Level 2 ===<br />
{{Quote|<br />
給一個 <math>N \times M</math> 的方格圖,其中每個格子皆有 黑/白 其中一個顏色。<br><br />
顏色符合以下條件:<br><br />
對於第 <math>i</math> 行,<math>1 \sim a_i</math> 為白色,而 <math>a_i + 1 \sim M</math> 為黑色<br><br />
對於 <math>1 \leq a_i \leq N-1</math>,<math>ai \leq a_i+1</math>。<br><br />
問是否可以用 <math>1 \times 2</math> 的骨牌將所有白色區塊填滿,使得任一個白色格子恰被一個骨牌覆蓋。<br />
}}<br />
由出題者完善的題目敘述,這樣的敘述能夠讓未看過題目的人在沒有額外口頭補充下理解題目。若沒有能力改寫成 Level 3 的題敘,在正式競賽中使用這種題敘尚可接受。<br />
<br />
=== Level 3 ===<br />
{{Quote|<br />
那是有一個魔法軍隊的戰爭時代,譚雅是帝國軍二〇三航空魔導大隊的大隊長。<br><br />
帝國的國力逐漸變得強大,引起鄰國的不安,想趕在被消滅前先下手為強。<br><br />
這天某個國家又跨越邊境前來進犯,譚雅奉命前去驅趕敵人。<br><br />
敵軍佔領的區域可以由左至右等距分成 <math>N</math> 格,而從邊境線往內陸也按相同距離切割成數格。<br><br />
譚雅發現越靠右方的戰線,離邊境的距離可能與相鄰左方相等或更遠。<br><br />
魔導大隊的魔法攻擊可以轟炸 <math>1 \times 2</math> 或 <math>2 \times 1</math>的方格。<br><br />
所有敵軍佔領的區域都必須轟炸,但為了節省資源,不想要重複轟炸相同格子,也不想轟炸沒有敵軍佔領的區域。<br><br />
請問譚雅是否能達成這個目標呢? <br />
}}<br />
經過故事設定的包裝,是正式競賽中常見的題目敘述,能夠讓參賽者充分理解題意。<br />
<br />
== 目的 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 賦予數值意義 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
{{Quote<br />
|給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
|原始題敘(Level 2)<br />
}}<br />
{{Quote<br />
|有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
|包裝題敘(Level 3)<br />
}}<br />
<br />
雖然原始題敘已經充分說明題目,但若僅使用原始題敘,參賽者可能就會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝,將數列轉換為飼料盆內的飼料量、K 轉換為嘴巴的容量、mod K 轉換為吞下飼料的行為,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 解決邏輯錯誤 ===<br />
{{TOJ side box|556|B. 舞會}}<br />
{{Quote|<br />
有 <math>N</math> 個人要爬 <math>K</math> 層樓梯。<br><br />
每個人一開始都在第 <math>0</math> 層,且第 <math>i</math> 個人會每秒上升 <math>a_i</math> 層。<br><br />
現在有 <math>M</math> 罐運動飲料,每一瓶可以讓第 <math>i</math> 個人瞬間上升 <math>b_i</math> 層。一個人可以喝多瓶,也可以完全不喝。<br><br />
請問在最優的分配下,最快幾秒可以讓所有人可以上升到樓梯頂部 ( 層數 <math>\ge K</math> 即視為在樓梯頂部 )。<br />
|未採用題敘(Level 3)<br />
}}<br />
{{Quote|<br />
雪乃和伊呂波在準備畢業舞會,準備工作非常繁雜,有 <math>N</math> 項工作需要完成。<br><br />
為了好好管理進度,雪乃將每項工作都等分成 <math>K</math> 份。<br><br />
而雪乃和伊呂波一起工作的話,對於第 <math>i</math> 項工作,每天可以完成那項工作的 <math>a_i</math> 份(每項工作每天都會做,且恰好完成 <math>a_i</math> 份,無法把時間挪用給其他工作,就算有一些項目的工作已經完成,也不會增加其他工作的效率)。<br><br />
但是怕工作做不完,恰好又有 <math>M</math> 筆經費,所以決定把部份工作外包。<br><br />
每筆經費對於第 <math>i</math> 項工作,可以將那項工作的 <math>b_i</math> 份外包,外包的部分可不計入花費時間直接視為完成。<br><br />
請問在最佳分配經費的情況下,最少幾天就能完成所有工作(不足一天以一天計)。<br />
|正式題敘(Level 3)<br />
}}<br />
雖然未採用題敘直接在正式競賽中使用並沒有什麼問題……但運動飲料可以讓人「瞬間」上升怎麼想都不合理,而且運動飲料不是增加每個人的體能而是讓人直接上升,所以對不同人的效果為何有不同效果(<math>b_i</math>)也缺乏合理解釋。改成工作外包後,不同工作在同樣經費下能外包的工作量本來就不同,而且外包也能作為工作量直接消失的理由。<br />
<br />
=== 測驗閱讀理解 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
{{Quote<br />
|輸出 1 就是答案。<br />
|根本是答案(Level 1)<br />
}}<br />
{{Quote<br />
|參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
|包裝題敘(Level 3)<br />
}}<br />
一個反例是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|507|A. 二分圖匹配(說明圖片位於第 2 頁最上方)<br />
|570|E. 存在X(說明圖片位於本文尾端)<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
{{clear}}<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
{{clear}}<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
{{Memo|'''簡而言之:'''<br />
# 壓縮圖片大小到寬度 640px 並轉換成 JPG 檔。<br />
# 標註圖片來源。<br />
|}}<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TOJ&diff=411
TOJ
2022-09-04T13:55:07Z
<p>Xiplus:</p>
<hr />
<div>[[Category:TOJ]]<br />
<br />
https://toj.tfcis.org/oj/<br />
<br />
* 社團練習用的Online Judge<br />
* 由[[T13]]的[[吳哲宇]]([[pzread]])開發<br />
* [[T19]]的[[lys0829]]於2017年將judge更新<br />
<br />
== Special Judge ==<br />
將[https://github.com/TFcis/Problem-setting-tools/blob/master/TOJ-problem-example/conf.json conf.json]中的check從diff改成ioredir,及設定metadata如下。<br />
;/conf.json<br />
<syntaxhighlight lang="JSON">{<br />
"check": "ioredir",<br />
"metadata": {<br />
"redir_test": {<br />
"pipeout": 1,<br />
"testin": 0,<br />
"testout": -1,<br />
"pipein": -1<br />
},<br />
"redir_check": {<br />
"ansin": 2,<br />
"testin": -1,<br />
"pipeout": 0,<br />
"pipein": -1<br />
}<br />
}<br />
}</syntaxhighlight><br />
<br />
;/res/check/check.cpp<br />
分別從答案及輸出分別讀入long double。<br />
<syntaxhighlight lang="C++"><br />
long double Answer, Output;<br />
FILE *ansf = fdopen(2, "r");<br />
<br />
scanf("%Lf", &Output);<br />
fscanf(ansf, "%Lf", &Answer);<br />
</syntaxhighlight><br />
<br />
;/res/check/build<br />
<syntaxhighlight lang="Bash"><br />
#!/bin/sh<br />
g++ -o check check.cpp<br />
</syntaxhighlight><br />
<br />
參考 https://hackmd.io/s/BkHdt57I<br />
<br />
== 參見 ==<br />
* [[TOJ API]]:API文檔<br />
* [https://github.com/pzread/judge judge原始碼]</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=410
TPS
2022-08-31T03:23:47Z
<p>Xiplus:/* 手產測資檔 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
# (可選)若要將 GitHub Repo 更新傳送到 Discord,請參考 [https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks Intro to Webhooks – Discord] 操作。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 範例測資亦可隨機產生,若想要手動指定,亦可使用手產測資檔。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例有 2 個範例測資,其中一個使用手產測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>,另一個為隨機測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 gen/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/gen/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 跳過自動建置 ===<br />
若已經啟用自動建置,但想在特定一筆 Commit 跳過自動建置,請在 Commit message 加上 <code>[no ci]</code>,例如:<br />
<syntaxhighlight lang="text">pA Add wa.cpp<br />
<br />
Add WA solution without swap<br />
[no ci]<br />
</syntaxhighlight><br />
<br />
完整說明參見 [https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs Skipping workflow runs - GitHub Docs]。</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=409
TPS
2022-08-30T09:51:10Z
<p>Xiplus:/* 自動建置 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
# (可選)若要將 GitHub Repo 更新傳送到 Discord,請參考 [https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks Intro to Webhooks – Discord] 操作。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 gen/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/gen/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 跳過自動建置 ===<br />
若已經啟用自動建置,但想在特定一筆 Commit 跳過自動建置,請在 Commit message 加上 <code>[no ci]</code>,例如:<br />
<syntaxhighlight lang="text">pA Add wa.cpp<br />
<br />
Add WA solution without swap<br />
[no ci]<br />
</syntaxhighlight><br />
<br />
完整說明參見 [https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs Skipping workflow runs - GitHub Docs]。</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=408
TPS
2022-08-29T01:22:53Z
<p>Xiplus:/* 自動建置測資 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
# (可選)若要將 GitHub Repo 更新傳送到 Discord,請參考 [https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks Intro to Webhooks – Discord] 操作。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 gen/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/gen/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=407
TPS
2022-08-29T01:21:40Z
<p>Xiplus:/* 自動建置測資 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
# (可選)若要將 GitHub Repo 更新傳送到 Discord,請參考 [https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks Intro to Webhooks – Discord] 操作。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 gen/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=406
題目敘述故事
2022-08-28T13:01:05Z
<p>Xiplus:/* 合理化題目 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 包裝程度比較 ==<br />
{{TOJ side box|570|E. 存在X}}<br />
以下使用的範例為 {{TOJ|570}}(109 學年度資訊學科能⼒競賽臺南⼀中校內複選,E. 存在X)在準備競賽時題目敘述演進過程的真實案例。<br />
<br />
=== Level 1 ===<br />
{{Quote|<br />
問是否可以以 <math>1 \times 2</math> 骨牌組成給定的遞增圖形。<br />
}}<br />
由出題者寫出來最原始的題目敘述,通常還需要額外的口頭補充解釋才能讓其他人理解題目,這樣的敘述僅能夠讓命題團隊的其他成員記得題目內容,但不足以在正式競賽中使用。<br />
<br />
=== Level 2 ===<br />
{{Quote|<br />
給一個 <math>N \times M</math> 的方格圖,其中每個格子皆有 黑/白 其中一個顏色。<br><br />
顏色符合以下條件:<br><br />
對於第 <math>i</math> 行,<math>1 \sim a_i</math> 為白色,而 <math>a_i + 1 \sim M</math> 為黑色<br><br />
對於 <math>1 \leq a_i \leq N-1</math>,<math>ai \leq a_i+1</math>。<br><br />
問是否可以用 <math>1 \times 2</math> 的骨牌將所有白色區塊填滿,使得任一個白色格子恰被一個骨牌覆蓋。<br />
}}<br />
由出題者完善的題目敘述,這樣的敘述能夠讓未看過題目的人在沒有額外口頭補充下理解題目。若沒有能力改寫成 Level 3 的題敘,在正式競賽中使用這種題敘尚可接受。<br />
<br />
=== Level 3 ===<br />
{{Quote|<br />
那是有一個魔法軍隊的戰爭時代,譚雅是帝國軍二〇三航空魔導大隊的大隊長。<br><br />
帝國的國力逐漸變得強大,引起鄰國的不安,想趕在被消滅前先下手為強。<br><br />
這天某個國家又跨越邊境前來進犯,譚雅奉命前去驅趕敵人。<br><br />
敵軍佔領的區域可以由左至右等距分成 <math>N</math> 格,而從邊境線往內陸也按相同距離切割成數格。<br><br />
譚雅發現越靠右方的戰線,離邊境的距離可能與相鄰左方相等或更遠。<br><br />
魔導大隊的魔法攻擊可以轟炸 <math>1 \times 2</math> 或 <math>2 \times 1</math>的方格。<br><br />
所有敵軍佔領的區域都必須轟炸,但為了節省資源,不想要重複轟炸相同格子,也不想轟炸沒有敵軍佔領的區域。<br><br />
請問譚雅是否能達成這個目標呢? <br />
}}<br />
經過故事設定的包裝,是正式競賽中常見的題目敘述,能夠讓參賽者充分理解題意。<br />
<br />
== 目的 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 賦予數值意義 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
{{Quote<br />
|給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
|原始題敘(Level 2)<br />
}}<br />
{{Quote<br />
|有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
|包裝題敘(Level 3)<br />
}}<br />
<br />
雖然原始題敘已經充分說明題目,但若僅使用原始題敘,參賽者可能就會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝,將數列轉換為飼料盆內的飼料量、K 轉換為嘴巴的容量、mod K 轉換為吞下飼料的行為,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 解決邏輯錯誤 ===<br />
{{TOJ side box|556|B. 舞會}}<br />
{{Quote|<br />
有 <math>N</math> 個人要爬 <math>K</math> 層樓梯。<br><br />
每個人一開始都在第 <math>0</math> 層,且第 <math>i</math> 個人會每秒上升 <math>a_i</math> 層。<br><br />
現在有 <math>M</math> 罐運動飲料,每一瓶可以讓第 <math>i</math> 個人瞬間上升 <math>b_i</math> 層。一個人可以喝多瓶,也可以完全不喝。<br><br />
請問在最優的分配下,最快幾秒可以讓所有人可以上升到樓梯頂部 ( 層數 <math>\ge K</math> 即視為在樓梯頂部 )。<br />
|未採用題敘(Level 3)<br />
}}<br />
{{Quote|<br />
雪乃和伊呂波在準備畢業舞會,準備工作非常繁雜,有 <math>N</math> 項工作需要完成。<br><br />
為了好好管理進度,雪乃將每項工作都等分成 <math>K</math> 份。<br><br />
而雪乃和伊呂波一起工作的話,對於第 <math>i</math> 項工作,每天可以完成那項工作的 <math>a_i</math> 份(每項工作每天都會做,且恰好完成 <math>a_i</math> 份,無法把時間挪用給其他工作,就算有一些項目的工作已經完成,也不會增加其他工作的效率)。<br><br />
但是怕工作做不完,恰好又有 <math>M</math> 筆經費,所以決定把部份工作外包。<br><br />
每筆經費對於第 <math>i</math> 項工作,可以將那項工作的 <math>b_i</math> 份外包,外包的部分可不計入花費時間直接視為完成。<br><br />
請問在最佳分配經費的情況下,最少幾天就能完成所有工作(不足一天以一天計)。<br />
|正式題敘(Level 3)<br />
}}<br />
雖然未採用題敘直接在正式競賽中使用並沒有什麼問題……但運動飲料可以讓人「瞬間」上升怎麼想都不合理,而且運動飲料不是增加每個人的體能而是讓人直接上升,所以對不同人的效果為何有不同效果(<math>b_i</math>)也缺乏合理解釋。改成工作外包後,不同工作在同樣經費下能外包的工作量本來就不同,而且外包也能作為工作量直接消失的理由。<br />
<br />
=== 測驗閱讀理解 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
{{Quote<br />
|輸出 1 就是答案。<br />
|根本是答案(Level 1)<br />
}}<br />
{{Quote<br />
|參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
|包裝題敘(Level 3)<br />
}}<br />
一個反例是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|507|A. 二分圖匹配(說明圖片位於第 2 頁最上方)<br />
|570|E. 存在X(說明圖片位於本文尾端)<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
{{clear}}<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
{{clear}}<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=405
題目敘述故事
2022-08-27T17:07:34Z
<p>Xiplus:+level範例 +目的</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 包裝程度比較 ==<br />
{{TOJ side box|570|E. 存在X}}<br />
以下使用的範例為 {{TOJ|570}}(109 學年度資訊學科能⼒競賽臺南⼀中校內複選,E. 存在X)在準備競賽時題目敘述演進過程的真實案例。<br />
<br />
=== Level 1 ===<br />
{{Quote|<br />
問是否可以以 <math>1 \times 2</math> 骨牌組成給定的遞增圖形。<br />
}}<br />
由出題者寫出來最原始的題目敘述,通常還需要額外的口頭補充解釋才能讓其他人理解題目,這樣的敘述僅能夠讓命題團隊的其他成員記得題目內容,但不足以在正式競賽中使用。<br />
<br />
=== Level 2 ===<br />
{{Quote|<br />
給一個 <math>N \times M</math> 的方格圖,其中每個格子皆有 黑/白 其中一個顏色。<br><br />
顏色符合以下條件:<br><br />
對於第 <math>i</math> 行,<math>1 \sim a_i</math> 為白色,而 <math>a_i + 1 \sim M</math> 為黑色<br><br />
對於 <math>1 \leq a_i \leq N-1</math>,<math>ai \leq a_i+1</math>。<br><br />
問是否可以用 <math>1 \times 2</math> 的骨牌將所有白色區塊填滿,使得任一個白色格子恰被一個骨牌覆蓋。<br />
}}<br />
由出題者完善的題目敘述,這樣的敘述能夠讓未看過題目的人在沒有額外口頭補充下理解題目。若沒有能力改寫成 Level 3 的題敘,在正式競賽中使用這種題敘尚可接受。<br />
<br />
=== Level 3 ===<br />
{{Quote|<br />
那是有一個魔法軍隊的戰爭時代,譚雅是帝國軍二〇三航空魔導大隊的大隊長。<br><br />
帝國的國力逐漸變得強大,引起鄰國的不安,想趕在被消滅前先下手為強。<br><br />
這天某個國家又跨越邊境前來進犯,譚雅奉命前去驅趕敵人。<br><br />
敵軍佔領的區域可以由左至右等距分成 <math>N</math> 格,而從邊境線往內陸也按相同距離切割成數格。<br><br />
譚雅發現越靠右方的戰線,離邊境的距離可能與相鄰左方相等或更遠。<br><br />
魔導大隊的魔法攻擊可以轟炸 <math>1 \times 2</math> 或 <math>2 \times 1</math>的方格。<br><br />
所有敵軍佔領的區域都必須轟炸,但為了節省資源,不想要重複轟炸相同格子,也不想轟炸沒有敵軍佔領的區域。<br><br />
請問譚雅是否能達成這個目標呢? <br />
}}<br />
經過故事設定的包裝,是正式競賽中常見的題目敘述,能夠讓參賽者充分理解題意。<br />
<br />
== 目的 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 賦予數值意義 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
{{Quote<br />
|給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
|原始題敘(Level 2)<br />
}}<br />
{{Quote<br />
|有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
|包裝題敘(Level 3)<br />
}}<br />
<br />
雖然原始題敘已經充分說明題目,但若僅使用原始題敘,參賽者可能就會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝,將數列轉換為飼料盆內的飼料量、K 轉換為嘴巴的容量、mod K 轉換為吞下飼料的行為,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 合理化題目 ===<br />
{{TOJ side box|556|B. 舞會}}<br />
{{Quote|<br />
有 <math>N</math> 個人要爬 <math>K</math> 層樓梯。<br><br />
每個人一開始都在第 <math>0</math> 層,且第 <math>i</math> 個人會每秒上升 <math>a_i</math> 層。<br><br />
現在有 <math>M</math> 罐運動飲料,每一瓶可以讓第 <math>i</math> 個人瞬間上升 <math>b_i</math> 層。一個人可以喝多瓶,也可以完全不喝。<br><br />
請問在最優的分配下,最快幾秒可以讓所有人可以上升到樓梯頂部 ( 層數 <math>\ge K</math> 即視為在樓梯頂部 )。<br />
|未採用題敘(Level 3)<br />
}}<br />
{{Quote|<br />
雪乃和伊呂波在準備畢業舞會,準備工作非常繁雜,有 <math>N</math> 項工作需要完成。<br><br />
為了好好管理進度,雪乃將每項工作都等分成 <math>K</math> 份。<br><br />
而雪乃和伊呂波一起工作的話,對於第 <math>i</math> 項工作,每天可以完成那項工作的 <math>a_i</math> 份(每項工作每天都會做,且恰好完成 <math>a_i</math> 份,無法把時間挪用給其他工作,就算有一些項目的工作已經完成,也不會增加其他工作的效率)。<br><br />
但是怕工作做不完,恰好又有 <math>M</math> 筆經費,所以決定把部份工作外包。<br><br />
每筆經費對於第 <math>i</math> 項工作,可以將那項工作的 <math>b_i</math> 份外包,外包的部分可不計入花費時間直接視為完成。<br><br />
請問在最佳分配經費的情況下,最少幾天就能完成所有工作(不足一天以一天計)。<br />
|正式題敘(Level 3)<br />
}}<br />
雖然未採用題敘直接在正式競賽中使用並沒有什麼問題……但運動飲料可以讓人「瞬間」上升怎麼想都不合理,而且運動飲料不是增加每個人的體能而是讓人直接上升,所以對不同人的效果為何有不同效果(<math>b_i</math>)也缺乏合理解釋。改成工作外包後,不同工作在同樣經費下能外包的工作量本來就不同,而且外包也能作為工作量直接消失的理由。<br />
<br />
=== 測驗閱讀理解 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
{{Quote<br />
|輸出 1 就是答案。<br />
|根本是答案(Level 1)<br />
}}<br />
{{Quote<br />
|參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
|包裝題敘(Level 3)<br />
}}<br />
一個反例是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|507|A. 二分圖匹配(說明圖片位於第 2 頁最上方)<br />
|570|E. 存在X(說明圖片位於本文尾端)<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
{{clear}}<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
{{clear}}<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=404
TPS
2022-08-27T13:58:02Z
<p>Xiplus:/* 建立GitHub Repo */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
# (可選)若要將 GitHub Repo 更新傳送到 Discord,請參考 [https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks Intro to Webhooks – Discord] 操作。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=403
TPS
2022-08-24T15:08:04Z
<p>Xiplus:/* 準備TPS資料 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱(problem title)使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱(problem name)應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號(problem label)為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(又稱官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式(generator)應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務(subtask)設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題目敘述(statement)的檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=402
TPS
2022-08-23T14:34:10Z
<p>Xiplus:/* 題目資料夾 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容通常由程式自動產生。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
[[File:Crystal Clear action run.png|20px]] 本目錄保存 TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本目錄內容由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
[[File:Crystal Clear action run.png|20px]] 本檔案由程式自動產生,不應手動編輯。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=401
TPS
2022-08-23T13:44:57Z
<p>Xiplus:/* 產測資指令 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=400
TPS
2022-08-21T16:23:41Z
<p>Xiplus:/* 刪除題目資料夾 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ===<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=399
TPS
2022-08-21T16:22:31Z
<p>Xiplus:</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 刪除題目資料夾 ====<br />
雖然這通常不會發生,但如果誤建過多題目等情況,需要刪除題目資料夾時,請務必完成以下所有操作:<br />
# 刪除{{slink||題目資料夾}}。<br />
# 從{{slink||.problems.json}}刪除題目編號。<br />
# 從{{slink||Makefile}}刪除對應題目的匯入指令。<br />
# 從{{slink||README.md}}刪除對應題目的連結。<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=398
TPS
2022-08-21T16:17:11Z
<p>Xiplus:</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== .problems.json ====<br />
記錄{{slink||題目資料夾}}列表,供 GitHub Actions {{slink||自動建置}}使用,通常不應手動修改。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=397
TPS
2022-08-19T07:54:58Z
<p>Xiplus:/* 提示 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
{{clear}}<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=396
TPS
2022-08-19T07:52:37Z
<p>Xiplus:/* 題目敘述 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||statement/index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=395
TPS
2022-08-19T07:47:52Z
<p>Xiplus:</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
==== .github/workflows ====<br />
GitHub 自動化流程設定檔。<br />
<br />
==== pX ====<br />
pA、pB 等{{slink||題目資料夾}}。<br />
<br />
==== Makefile ====<br />
[[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
<br />
==== README.md ====<br />
主要在 GitHub 頁面上提供常用連結。<br />
<br />
==== cover.tex ====<br />
題本封面。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex<br />
<br />
==== template.tex ====<br />
題本內文模板,通常無需修改。<br />
<br />
=== 題目資料夾 ===<br />
==== attachments ====<br />
放在此處的所有檔案將會上傳到 CMS 上,供參賽者在題目敘述頁的「附件」,通常僅會在 pA 的附件放置{{slink||合併題本}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pA/attachments<br />
<br />
==== gen ====<br />
放置{{slink||產測資}}相關的所有檔案。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen<br />
<br />
==== gen/manual ====<br />
{{See also|#手產測資檔}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual<br />
<br />
==== gen/data ====<br />
{{See also|#產測資指令}}<br />
<br />
==== scripts ====<br />
TPS scripts,不需修改。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/scripts<br />
<br />
==== solution ====<br />
{{See also|#標程}}<br />
<br />
==== statement ====<br />
題本相關檔案,包含原始碼、圖片、{{slink||建置題本}}產生的 PDF。<br />
<br />
==== statement/index.md ====<br />
{{See also|#題目敘述}}<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md<br />
<br />
==== tests ====<br />
{{slink||產測資}}後的檔案會存放於此,參見{{slink||建置測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests<br />
<br />
==== validator ====<br />
{{See also|#驗測資程式}}<br />
<br />
==== problem.json ====<br />
題目的相關設定,參見{{slink||競賽名稱|題目名稱|題目英文名稱|題目編號|記憶體限制|時間限制}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json<br />
<br />
==== solutions-check.txt ====<br />
所有標程的執行結果報告。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt<br />
<br />
==== solutions.json ====<br />
列出所有{{slink||標程}}及其 verdict,標記為 model_solution 的標程會用於{{slink||產測資}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json<br />
<br />
==== subtasks.json ====<br />
列出所有的{{slink||子任務}},及每個子任務所使用的{{slink||驗測資程式}}。<br />
<br />
範例:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目資料夾建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# {{slink||cover.tex}}。<br />
# 各題目{{slink||problem.json}}的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於{{slink||problem.json}}的 title 欄位,範例為「Piñata」。<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於{{slink||problem.json}}的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於{{slink||problem.json}}的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
=== 時間限制 ===<br />
需寫入於{{slink||problem.json}}的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在{{slink||solution}}資料夾內,檔名無限制。同時將該檔名寫入{{slink||solutions.json}},格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在{{slink||gen/manual}}資料夾內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在{{slink||gen}}資料夾內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在{{slink||gen/data}},以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在{{slink||子任務配分}}。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在{{slink||gen/manual}}資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在{{slink||validator}}資料夾內,檔名無限制,並將檔名寫入{{slink||subtasks.json}}的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在{{slink||subtasks.json}}中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在{{slink||subtasks.json}}中設定為測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於{{slink||標程}}的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於{{slink||subtasks.json}},包含各子任務的配分、文字描述、{{slink||驗測資程式}}。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的{{slink||驗測資程式}}。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與{{slink||產測資指令}}中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的{{slink||驗測資程式}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於{{slink||index.md}}。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# {{slink||題目圖片}}<br />
# {{slink||題目本文}}<br />
# 輸入(說明),參見{{slink||輸入及輸出說明}}<br />
# 輸出(說明),參見{{slink||輸入及輸出說明}}<br />
# {{slink||輸入限制}}<br />
# {{slink||子任務}}說明<br />
# 範例輸入,參見{{slink||範例輸入及輸出}}<br />
# 範例輸出,參見{{slink||範例輸入及輸出}}<br />
# {{slink||提示}}<br />
<br />
==== 題目圖片 ====<br />
參見{{slink|題目敘述故事|插圖}}。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見{{slink||子任務}}的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與{{slink||產測資}}中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入{{slink||題目編號}},例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* {{slink||cover.tex}}僅會構建 pA 的題本<br />
* {{slink||problem.json}}的<br />
** contest_name:{{slink||競賽名稱}}<br />
** problem_label:{{slink||題目編號}}<br />
** name:{{slink||題目英文名稱}}<br />
** title:{{slink||題目名稱}}<br />
** memory_limit:{{slink||記憶體限制}}<br />
** time_limit:{{slink||時間限制}}<br />
* {{slink||subtasks.json}}的 index、score、text ,參見{{slink||子任務}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考{{slink||建置題本}}的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了{{slink||產測資}}程式,在 Problem labels to build inputs 輸入{{slink||題目編號}},例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了{{slink||標程}},導致僅有輸出會變動,在 Problem labels to build outputs 輸入{{slink||題目編號}},其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入{{slink||題目編號}}。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的{{slink||tests}}資料夾找到建置的測資。標程測試則在{{slink||solutions-check.txt}}。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* {{slink||gen}}內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在{{slink||solutions.json}}內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標檔案可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* {{slink||solution}}內的所有檔案<br />
* {{slink||solutions.json}}<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Module:Section_link&diff=394
Module:Section link
2022-08-19T07:11:18Z
<p>Xiplus:</p>
<hr />
<div>-- This module implements {{section link}}.<br />
require('Module:No globals');<br />
<br />
local checkType = require('libraryUtil').checkType<br />
<br />
local p = {}<br />
<br />
local function makeSectionLink(page, section, display)<br />
display = display or section<br />
page = page or ''<br />
-- MediaWiki doesn't allow these in `page`, so only need to do for `section`<br />
if type(section) == 'string' then<br />
section = string.gsub(section, "{", "&#x7B;")<br />
section = string.gsub(section, "}", "&#x7D;")<br />
end<br />
return string.format('[[%s#%s|%s]]', page, section, display)<br />
end<br />
<br />
local function normalizeTitle(title)<br />
title = mw.ustring.gsub(mw.ustring.gsub(title, "'", ""), '"', '')<br />
title = mw.ustring.gsub(title, "%b<>", "")<br />
return mw.title.new(title).prefixedText<br />
end<br />
<br />
function p._main(page, sections, options, title)<br />
-- Validate input.<br />
checkType('_main', 1, page, 'string', true)<br />
checkType('_main', 3, options, 'table', true)<br />
if sections == nil then<br />
sections = {}<br />
elseif type(sections) == 'string' then<br />
sections = {sections}<br />
elseif type(sections) ~= 'table' then<br />
error(string.format(<br />
"type error in argument #2 to '_main' " ..<br />
"(string, table or nil expected, got %s)",<br />
type(sections)<br />
), 2)<br />
end<br />
options = options or {}<br />
title = title or mw.title.getCurrentTitle()<br />
<br />
-- Deal with blank page names elegantly<br />
if page and not page:find('%S') then<br />
page = nil<br />
options.nopage = true<br />
end<br />
<br />
-- Make the link(s).<br />
local isShowingPage = not options.nopage<br />
if #sections <= 1 then<br />
local linkPage = page or ''<br />
local section = sections[1] or 'Notes'<br />
local display = '§&nbsp;' .. section<br />
if isShowingPage then<br />
page = page or title.prefixedText<br />
if options.display and options.display ~= '' then<br />
if normalizeTitle(options.display) == normalizeTitle(page) then<br />
display = options.display .. ' ' .. display<br />
else<br />
error(string.format(<br />
'Display title "%s" was ignored since it is ' ..<br />
"not equivalent to the page's actual title",<br />
options.display<br />
), 0)<br />
end<br />
else<br />
display = page .. ' ' .. display<br />
end<br />
end<br />
return makeSectionLink(linkPage, section, display)<br />
else<br />
-- Multiple sections. First, make a list of the links to display.<br />
local ret = {}<br />
for i, section in ipairs(sections) do<br />
ret[i] = makeSectionLink(page, section)<br />
end<br />
<br />
-- Assemble the list of links into a string with mw.text.listToText.<br />
-- We use the default separator for mw.text.listToText, but a custom<br />
-- conjunction. There is also a special case conjunction if we only<br />
-- have two links.<br />
local conjunction<br />
if #sections == 2 then<br />
conjunction = '&#8203;和'<br />
else<br />
conjunction = '&#8203;和'<br />
end<br />
ret = mw.text.listToText(ret, nil, conjunction)<br />
<br />
-- Add the intro text.<br />
local intro = '§§&nbsp;'<br />
if isShowingPage then<br />
intro = (page or title.prefixedText) .. ' ' .. intro<br />
end<br />
ret = intro .. ret<br />
<br />
return ret<br />
end<br />
end<br />
<br />
function p.main(frame)<br />
local yesno = require('Module:Yesno')<br />
local args = require('Module:Arguments').getArgs(frame, {<br />
wrappers = 'Template:Section link',<br />
valueFunc = function (key, value)<br />
value = value:match('^%s*(.-)%s*$') -- Trim whitespace<br />
-- Allow blank first parameters, as the wikitext template does this.<br />
if value ~= '' or key == 1 then<br />
return value<br />
end<br />
end<br />
})<br />
<br />
for k, v in pairs(args) do -- replace underscores in the positional parameter values<br />
if 'number' == type(k) then<br />
if not yesno (args['keep-underscores']) then -- unless |keep-underscores=yes<br />
args[k] = mw.uri.decode (v, 'WIKI'); -- percent-decode; replace underscores with space characters<br />
else<br />
args[k] = mw.uri.decode (v, 'PATH'); -- percent-decode; retain underscores<br />
end<br />
end<br />
end<br />
<br />
-- Sort the arguments.<br />
local page<br />
local sections, options = {}, {}<br />
for k, v in pairs(args) do<br />
if k == 1 then<br />
-- Doing this in the loop because of a bug in [[Module:Arguments]]<br />
-- when using pairs with deleted arguments.<br />
page = mw.text.decode(v, true)<br />
elseif type(k) == 'number' then<br />
sections[k] = v<br />
else<br />
options[k] = v<br />
end<br />
end<br />
<br />
options.nopage = yesno (options.nopage); -- make boolean<br />
<br />
-- Extract section from page, if present<br />
if page then<br />
local p, s = page:match('^(.-)#(.*)$')<br />
if p then page, sections[1] = p, s end<br />
end<br />
<br />
-- Compress the sections array.<br />
local function compressArray(t)<br />
local nums, ret = {}, {}<br />
for num in pairs(t) do<br />
nums[#nums + 1] = num<br />
end<br />
table.sort(nums)<br />
for i, num in ipairs(nums) do<br />
ret[i] = t[num]<br />
end<br />
return ret<br />
end<br />
sections = compressArray(sections)<br />
<br />
return p._main(page, sections, options)<br />
end<br />
<br />
return p</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Module:Section_link&diff=393
Module:Section link
2022-08-19T07:04:54Z
<p>Xiplus:已從:zhwiki:Module:Section_link匯入1筆修訂</p>
<hr />
<div>-- This module implements {{section link}}.<br />
require('Module:No globals');<br />
<br />
local checkType = require('libraryUtil').checkType<br />
<br />
local p = {}<br />
<br />
local function makeSectionLink(page, section, display)<br />
display = display or section<br />
page = page or ''<br />
-- MediaWiki doesn't allow these in `page`, so only need to do for `section`<br />
if type(section) == 'string' then<br />
section = string.gsub(section, "{", "&#x7B;")<br />
section = string.gsub(section, "}", "&#x7D;")<br />
end<br />
return string.format('[[%s#%s|%s]]', page, section, display)<br />
end<br />
<br />
local function normalizeTitle(title)<br />
title = mw.ustring.gsub(mw.ustring.gsub(title, "'", ""), '"', '')<br />
title = mw.ustring.gsub(title, "%b<>", "")<br />
return mw.title.new(title).prefixedText<br />
end<br />
<br />
function p._main(page, sections, options, title)<br />
-- Validate input.<br />
checkType('_main', 1, page, 'string', true)<br />
checkType('_main', 3, options, 'table', true)<br />
if sections == nil then<br />
sections = {}<br />
elseif type(sections) == 'string' then<br />
sections = {sections}<br />
elseif type(sections) ~= 'table' then<br />
error(string.format(<br />
"type error in argument #2 to '_main' " ..<br />
"(string, table or nil expected, got %s)",<br />
type(sections)<br />
), 2)<br />
end<br />
options = options or {}<br />
title = title or mw.title.getCurrentTitle()<br />
<br />
-- Deal with blank page names elegantly<br />
if page and not page:find('%S') then<br />
page = nil<br />
options.nopage = true<br />
end<br />
<br />
-- Make the link(s).<br />
local isShowingPage = not options.nopage<br />
if #sections <= 1 then<br />
local linkPage = page or ''<br />
local section = sections[1] or 'Notes'<br />
local display = '§&nbsp;' .. section<br />
if isShowingPage then<br />
page = page or title.prefixedText<br />
if options.display and options.display ~= '' then<br />
if normalizeTitle(options.display) == normalizeTitle(page) then<br />
display = options.display .. ' ' .. display<br />
else<br />
error(string.format(<br />
'Display title "%s" was ignored since it is ' ..<br />
"not equivalent to the page's actual title",<br />
options.display<br />
), 0)<br />
end<br />
else<br />
display = page .. ' ' .. display<br />
end<br />
end<br />
return makeSectionLink(linkPage, section, display)<br />
else<br />
-- Multiple sections. First, make a list of the links to display.<br />
local ret = {}<br />
for i, section in ipairs(sections) do<br />
ret[i] = makeSectionLink(page, section)<br />
end<br />
<br />
-- Assemble the list of links into a string with mw.text.listToText.<br />
-- We use the default separator for mw.text.listToText, but a custom<br />
-- conjunction. There is also a special case conjunction if we only<br />
-- have two links.<br />
local conjunction<br />
if #sections == 2 then<br />
conjunction = '&#8203; 和 '<br />
else<br />
conjunction = '&#8203; 和 '<br />
end<br />
ret = mw.text.listToText(ret, nil, conjunction)<br />
<br />
-- Add the intro text.<br />
local intro = '§§&nbsp;'<br />
if isShowingPage then<br />
intro = (page or title.prefixedText) .. ' ' .. intro<br />
end<br />
ret = intro .. ret<br />
<br />
return ret<br />
end<br />
end<br />
<br />
function p.main(frame)<br />
local yesno = require('Module:Yesno')<br />
local args = require('Module:Arguments').getArgs(frame, {<br />
wrappers = 'Template:Section link',<br />
valueFunc = function (key, value)<br />
value = value:match('^%s*(.-)%s*$') -- Trim whitespace<br />
-- Allow blank first parameters, as the wikitext template does this.<br />
if value ~= '' or key == 1 then<br />
return value<br />
end<br />
end<br />
})<br />
<br />
for k, v in pairs(args) do -- replace underscores in the positional parameter values<br />
if 'number' == type(k) then<br />
if not yesno (args['keep-underscores']) then -- unless |keep-underscores=yes<br />
args[k] = mw.uri.decode (v, 'WIKI'); -- percent-decode; replace underscores with space characters<br />
else<br />
args[k] = mw.uri.decode (v, 'PATH'); -- percent-decode; retain underscores<br />
end<br />
end<br />
end<br />
<br />
-- Sort the arguments.<br />
local page<br />
local sections, options = {}, {}<br />
for k, v in pairs(args) do<br />
if k == 1 then<br />
-- Doing this in the loop because of a bug in [[Module:Arguments]]<br />
-- when using pairs with deleted arguments.<br />
page = mw.text.decode(v, true)<br />
elseif type(k) == 'number' then<br />
sections[k] = v<br />
else<br />
options[k] = v<br />
end<br />
end<br />
<br />
options.nopage = yesno (options.nopage); -- make boolean<br />
<br />
-- Extract section from page, if present<br />
if page then<br />
local p, s = page:match('^(.-)#(.*)$')<br />
if p then page, sections[1] = p, s end<br />
end<br />
<br />
-- Compress the sections array.<br />
local function compressArray(t)<br />
local nums, ret = {}, {}<br />
for num in pairs(t) do<br />
nums[#nums + 1] = num<br />
end<br />
table.sort(nums)<br />
for i, num in ipairs(nums) do<br />
ret[i] = t[num]<br />
end<br />
return ret<br />
end<br />
sections = compressArray(sections)<br />
<br />
return p._main(page, sections, options)<br />
end<br />
<br />
return p</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Template:Slink&diff=391
Template:Slink
2022-08-19T07:04:38Z
<p>Xiplus:已從:zhwiki:Template:Slink匯入1筆修訂</p>
<hr />
<div>#重定向 [[Template:Section link]]</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Template:Section_link&diff=389
Template:Section link
2022-08-19T07:04:04Z
<p>Xiplus:已從:zhwiki:Template:Section_link匯入1筆修訂</p>
<hr />
<div>{{#invoke:Section link|main}}<noinclude><br />
{{Documentation}}</noinclude></div>
Xiplus
https://wiki.tfcis.org/index.php?title=Module:Hatnote_list&diff=387
Module:Hatnote list
2022-08-19T07:01:56Z
<p>Xiplus:已從:zhwiki:Module:Hatnote_list匯入1筆修訂</p>
<hr />
<div>--------------------------------------------------------------------------------<br />
-- Module:Hatnote list --<br />
-- --<br />
-- This module produces and formats lists for use in hatnotes. In particular, --<br />
-- it implements the for-see list, i.e. lists of "For X, see Y" statements, --<br />
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced --<br />
-- are andList & orList helpers for formatting lists with those conjunctions. --<br />
--------------------------------------------------------------------------------<br />
<br />
local mArguments --initialize lazily<br />
local mHatnote = require('Module:Hatnote')<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
local p = {}<br />
<br />
--------------------------------------------------------------------------------<br />
-- List stringification helper functions<br />
--<br />
-- These functions are used for stringifying lists, usually page lists inside<br />
-- the "Y" portion of "For X, see Y" for-see items.<br />
--------------------------------------------------------------------------------<br />
<br />
--default options table used across the list stringification functions<br />
-- 本地化注意<br />
local stringifyListDefaultOptions = {<br />
conjunction = "和",<br />
separator = "、",<br />
altSeparator = ";",<br />
space = "",<br />
formatted = false,<br />
boldfaced = false,<br />
quotes = false<br />
}<br />
<br />
-- Stringifies a list generically; probably shouldn't be used directly<br />
function stringifyList(list, options)<br />
-- Type-checks, defaults, and a shortcut<br />
checkType("stringifyList", 1, list, "table")<br />
if #list == 0 then return nil end<br />
checkType("stringifyList", 2, options, "table", true)<br />
options = options or {}<br />
for k, v in pairs(stringifyListDefaultOptions) do<br />
if options[k] == nil then options[k] = v end<br />
end<br />
local s = options.space<br />
-- Format the list if requested<br />
if options.formatted then list = mHatnote.formatPages(unpack(list)) end<br />
-- Set the separator; if any item contains it, use the alternate separator<br />
local separator = options.separator<br />
--searches display text only<br />
function searchDisp(t, f)<br />
return string.find(string.sub(t, (string.find(t, '|') or 0) + 1), f)<br />
end<br />
for k, v in pairs(list) do<br />
-- 本地化注意<br />
if options.boldfaced then<br />
list[k] = '\'\'\'' .. list[k] .. '\'\'\''<br />
end<br />
if options.quotes then<br />
list[k] = '「' .. list[k] .. '」'<br />
end<br />
if searchDisp(v, separator) then<br />
separator = options.altSeparator<br />
break<br />
end<br />
end<br />
-- Set the conjunction, apply Oxford comma, and force a comma if #1 has "§"<br />
local conjunction = s .. options.conjunction .. s<br />
-- 本地化注意<br />
-- separator .. conjunction的结果是“、和”<br />
-- if #list == 2 and searchDisp(list[1], "§") or #list > 2 then<br />
-- conjunction = separator .. conjunction<br />
-- end<br />
-- Return the formatted string<br />
return mw.text.listToText(list, separator .. s, conjunction)<br />
end<br />
<br />
--DRY function<br />
-- 本地化注意<br />
function conjList (conj, list, fmt, bold, quo)<br />
return stringifyList(list, {conjunction = conj, formatted = fmt, boldfaced = bold, quotes=quo})<br />
end<br />
<br />
-- Stringifies lists with "and" or "or"<br />
-- 本地化注意<br />
function p.andList (...) return conjList("和", ...) end<br />
function p.orList (...) return conjList("或", ...) end<br />
<br />
--------------------------------------------------------------------------------<br />
-- For see<br />
--<br />
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the<br />
-- {{about}} and {{redirect}} templates and their variants.<br />
--------------------------------------------------------------------------------<br />
<br />
--default options table used across the forSee family of functions<br />
-- 本地化注意<br />
local forSeeDefaultOptions = {<br />
andKeyword = '和',<br />
title = mw.title.getCurrentTitle().text,<br />
otherText = '其他用法',<br />
forSeeForm = '关于%s,请见%s。',<br />
}<br />
<br />
--Collapses duplicate punctuation<br />
-- 本地化注意<br />
function punctuationCollapse (text)<br />
local replacements = {<br />
["%.%.$"] = ".",<br />
["%?%.$"] = "?",<br />
["%!%.$"] = "!",<br />
["%.%]%]%.$"] = ".]]",<br />
["%?%]%]%.$"] = "?]]",<br />
["%!%]%]%.$"] = "!]]",<br />
["%。%。$"] = "。",<br />
["%?%。$"] = "?",<br />
["%!%。$"] = "!",<br />
["%。%]%]%。$"] = "。]]",<br />
["%?%]%]%。$"] = "?]]",<br />
["%!%]%]%。$"] = "!]]"<br />
}<br />
for k, v in pairs(replacements) do text = string.gsub(text, k, v) end<br />
return text<br />
end<br />
<br />
-- Structures arguments into a table for stringification, & options<br />
function p.forSeeArgsToTable (args, from, options)<br />
-- Type-checks and defaults<br />
checkType("forSeeArgsToTable", 1, args, 'table')<br />
checkType("forSeeArgsToTable", 2, from, 'number', true)<br />
from = from or 1<br />
checkType("forSeeArgsToTable", 3, options, 'table', true)<br />
options = options or {}<br />
for k, v in pairs(forSeeDefaultOptions) do<br />
if options[k] == nil then options[k] = v end<br />
end<br />
-- maxArg's gotten manually because getArgs() and table.maxn aren't friends<br />
local maxArg = 0<br />
for k, v in pairs(args) do<br />
if type(k) == 'number' and k > maxArg then maxArg = k end<br />
end<br />
-- Structure the data out from the parameter list:<br />
-- * forTable is the wrapper table, with forRow rows<br />
-- * Rows are tables of a "use" string & a "pages" table of pagename strings<br />
-- * Blanks are left empty for defaulting elsewhere, but can terminate list<br />
local forTable = {}<br />
local i = from<br />
local terminated = false<br />
-- If there is extra text, and no arguments are given, give nil value<br />
-- to not produce default of "For other uses, see foo (disambiguation)"<br />
if options.extratext and i > maxArg then return nil end<br />
-- Loop to generate rows<br />
repeat<br />
-- New empty row<br />
local forRow = {}<br />
-- On blank use, assume list's ended & break at end of this loop<br />
forRow.use = args[i]<br />
if not args[i] then terminated = true end<br />
-- New empty list of pages<br />
forRow.pages = {}<br />
-- Insert first pages item if present<br />
table.insert(forRow.pages, args[i + 1])<br />
-- If the param after next is "and", do inner loop to collect params<br />
-- until the "and"'s stop. Blanks are ignored: "1|and||and|3" → {1, 3}<br />
while args[i + 2] == options.andKeyword do<br />
if args[i + 3] then <br />
table.insert(forRow.pages, args[i + 3])<br />
end<br />
-- Increment to next "and"<br />
i = i + 2<br />
end<br />
-- Increment to next use<br />
i = i + 2<br />
-- Append the row<br />
table.insert(forTable, forRow)<br />
until terminated or i > maxArg<br />
<br />
return forTable<br />
end<br />
<br />
-- Stringifies a table as formatted by forSeeArgsToTable<br />
function p.forSeeTableToString (forSeeTable, options)<br />
-- Type-checks and defaults<br />
checkType("forSeeTableToString", 1, forSeeTable, "table", true)<br />
checkType("forSeeTableToString", 2, options, "table", true)<br />
options = options or {}<br />
for k, v in pairs(forSeeDefaultOptions) do<br />
if options[k] == nil then options[k] = v end<br />
end<br />
-- Stringify each for-see item into a list<br />
local strList = {}<br />
if forSeeTable then<br />
for k, v in pairs(forSeeTable) do<br />
local useStr = v.use or options.otherText<br />
-- 本地化注意<br />
local pagesStr = p.andList(v.pages, true, true, true) or '「\'\'\'' .. mHatnote._formatLink(mHatnote.disambiguate(options.title)) .. '\'\'\'」'<br />
local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)<br />
forSeeStr = punctuationCollapse(forSeeStr)<br />
table.insert(strList, forSeeStr)<br />
end<br />
end<br />
if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..'。')) end<br />
-- Return the concatenated list<br />
return table.concat(strList)<br />
end<br />
<br />
-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps<br />
-- but not blank/whitespace values. Ignores named args and args < "from".<br />
function p._forSee (args, from, options)<br />
local forSeeTable = p.forSeeArgsToTable(args, from, options)<br />
return p.forSeeTableToString(forSeeTable, options)<br />
end<br />
<br />
-- As _forSee, but uses the frame.<br />
function p.forSee (frame, from, options)<br />
mArguments = require('Module:Arguments')<br />
return p._forSee(mArguments.getArgs(frame), from, options)<br />
end<br />
<br />
return p</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Module:Labelled_list_hatnote&diff=385
Module:Labelled list hatnote
2022-08-19T07:01:35Z
<p>Xiplus:已從:zhwiki:Module:Labelled_list_hatnote匯入1筆修訂</p>
<hr />
<div>--------------------------------------------------------------------------------<br />
-- Labelled list --<br />
-- --<br />
-- This module does the core work of creating a hatnote composed of a list --<br />
-- prefixed by a colon-terminated label, i.e. "LABEL: [andList of pages]", --<br />
-- for {{see also}} and similar templates. --<br />
--------------------------------------------------------------------------------<br />
<br />
local mHatnote = require('Module:Hatnote')<br />
local mHatlist = require('Module:Hatnote list')<br />
local mArguments --initialize lazily<br />
local p = {}<br />
<br />
-- Defaults global to this module<br />
-- 本地化注意<br />
local defaults = {<br />
label = '参见', --Final fallback for label argument<br />
labelForm = '%s:%s',<br />
prefixes = {'label', 'label ', 'l'},<br />
template = 'Module:Labelled list hatnote'<br />
}<br />
<br />
-- Helper function that pre-combines display parameters into page arguments.<br />
-- Also compresses sparse arrays, as a desirable side-effect.<br />
function p.preprocessDisplays (args, prefixes)<br />
-- Prefixes specify which parameters, in order, to check for display options<br />
-- They each have numbers auto-appended, e.g. 'label1', 'label 1', & 'l1'<br />
prefixes = prefixes or defaults.prefixes<br />
local pages = {}<br />
for k, v in pairs(args) do<br />
if type(k) == 'number' then<br />
local display<br />
for i = 1, #prefixes do<br />
display = args[prefixes[i] .. k]<br />
if display then break end<br />
end<br />
local page = display and<br />
string.format('%s|%s', string.gsub(v, '|.*$', ''), display) or v<br />
pages[#pages + 1] = page<br />
end<br />
end<br />
return pages<br />
end<br />
<br />
-- Produces a labelled pages-list hatnote.<br />
-- The main frame (template definition) takes 1 or 2 arguments, for a singular<br />
-- and (optionally) plural label respectively:<br />
-- * {{#invoke:Labelled list hatnote|labelledList|Singular label|Plural label}}<br />
-- The resulting template takes pagename & label parameters normally.<br />
function p.labelledList (frame)<br />
mArguments = require('Module:Arguments')<br />
local labels = {frame.args[1] or defaults.label}<br />
labels[2] = frame.args[2] or labels[1]<br />
local template = frame:getParent():getTitle()<br />
local args = mArguments.getArgs(frame, {parentOnly = true})<br />
local pages = p.preprocessDisplays(args)<br />
local options = {<br />
extraclasses = frame.args.extraclasses,<br />
category = args.category,<br />
selfref = frame.args.selfref or args.selfref,<br />
template = template<br />
}<br />
return p._labelledList(pages, labels, options)<br />
end<br />
<br />
function p._labelledList (pages, labels, options)<br />
labels = labels or {}<br />
if #pages == 0 then<br />
-- 本地化注意<br />
return mHatnote.makeWikitextError(<br />
'未指定页面名称',<br />
(options.template or defaults.template) .. '#错误',<br />
options.category<br />
)<br />
end<br />
label = (#pages == 1 and labels[1] or labels[2]) or defaults.label<br />
local text = string.format(<br />
options.labelForm or defaults.labelForm,<br />
label,<br />
mHatlist.andList(pages, true)<br />
)<br />
local hnOptions = {<br />
extraclasses = options.extraclasses,<br />
selfref = options.selfref<br />
}<br />
return mHatnote._hatnote(text, hnOptions)<br />
end<br />
<br />
return p</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Template:See_also&diff=383
Template:See also
2022-08-19T07:01:32Z
<p>Xiplus:</p>
<hr />
<div><includeonly>{{#invoke:Labelled list hatnote|labelledList|參見}}</includeonly><noinclude><br />
{{documentation}}<br />
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --><br />
</noinclude></div>
Xiplus
https://wiki.tfcis.org/index.php?title=Template:See_also&diff=382
Template:See also
2022-08-19T07:01:17Z
<p>Xiplus:已從:zhwiki:Template:See_also匯入1筆修訂</p>
<hr />
<div><includeonly>{{#invoke:Labelled list hatnote|labelledList|参见}}</includeonly><noinclude><br />
{{documentation}}<br />
<!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --><br />
</noinclude></div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=380
TPS
2022-08-19T06:48:34Z
<p>Xiplus:/* 自動建置測資 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入[[#題目編號|題目編號]],例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* cover.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref> 僅會構建 pA 的題本<br />
* problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的<br />
** contest_name:[[#競賽名稱|競賽名稱]]<br />
** problem_label:[[#題目編號|題目編號]]<br />
** name:[[#題目英文名稱|題目英文名稱]]<br />
** title:[[#題目名稱|題目名稱]]<br />
** memory_limit:[[#記憶體限制|記憶體限制]]<br />
** time_limit:[[#時間限制|時間限制]]<br />
* subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 index、score、text ,參見[[#子任務|子任務]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考[[#建置題本]]的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了[[#產測資|產測資程式]],在 Problem labels to build inputs 輸入[[#題目編號|題目編號]],例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了[[#標程|標程]],導致僅有輸出會變動,在 Problem labels to build outputs 輸入[[#題目編號|題目編號]],其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入[[#題目編號|題目編號]]。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的 tests 資料夾找到建置的測資<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests</ref>。標程測試則在 solutions-check.txt<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 tests/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
修改以下檔案將會觸發自動建置 input:<br />
* gen/**<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref> 內的所有檔案<br />
<br />
修改以下檔案將會觸發自動建置 output:<br />
* 在 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> 內設定的 model_solution 對應檔案。請注意:若變更 model_solution 的目標可能不會觸發自動建置。<br />
<br />
修改以下檔案將會觸發自動建置 solutions:<br />
* solution/**<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 內的所有檔案<br />
* solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref><br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=379
TPS
2022-08-19T06:39:48Z
<p>Xiplus:/* 自動建置題本 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入[[#題目編號|題目編號]],例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
修改以下檔案將會觸發自動建置:<br />
* scripts/statement.sh<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/scripts/statement.sh</ref><br />
* statement/*.jpg<ref>例如:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/cover.jpg</ref><br />
* statement/index.md<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md</ref><br />
* template.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/template.tex</ref><br />
* cover.tex<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref> 僅會構建 pA 的題本<br />
* problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的<br />
** contest_name:[[#競賽名稱|競賽名稱]]<br />
** problem_label:[[#題目編號|題目編號]]<br />
** name:[[#題目英文名稱|題目英文名稱]]<br />
** title:[[#題目名稱|題目名稱]]<br />
** memory_limit:[[#記憶體限制|記憶體限制]]<br />
** time_limit:[[#時間限制|時間限制]]<br />
* subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 index、score、text ,參見[[#子任務|子任務]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考[[#建置題本]]的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了[[#產測資|產測資程式]],在 Problem labels to build inputs 輸入[[#題目編號|題目編號]],例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了[[#標程|標程]],導致僅有輸出會變動,在 Problem labels to build outputs 輸入[[#題目編號|題目編號]],其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入[[#題目編號|題目編號]]。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的 tests 資料夾找到建置的測資<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests</ref>。標程測試則在 solutions-check.txt<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=378
TPS
2022-08-19T03:57:14Z
<p>Xiplus:</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備GitHub Repo ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 準備TPS資料 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== [[zhwiki:組建自動化|自動建置]] ==<br />
tps-starter<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref> 使用了 GitHub Actions<ref>https://github.com/features/actions</ref>,對於建置題本和測資提供了簡易介面來執行構建,並包含自動建置、自動化測試等功能。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置題本 ===<br />
若要將題本編譯成 PDF,按照以下步驟操作:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-pdf.yml</ref><br />
# 點擊 Run workflow,在 Problem labels to build 輸入[[#題目編號|題目編號]],例如「B」。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待 PDF 題本建置完成,約 2 分鐘。<br />
# 可在對應題目的 statement/index.pdf 找到建置的 PDF。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置題本 ===<br />
若題本已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置題本。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 合併題本 ===<br />
在所有題目的題本皆完成,才進行合併題本,參考[[#建置題本]]的操作,在第 4 步驟的 Problem labels to build 輸入「+」,即會合併題本輸出於 pA/attachments/problems.pdf。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pA/attachments/problems.pdf</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 建置測資 ===<br />
若要自動產生測資 input、output、進行標程比較:<br />
# 進入 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 Build tests。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/build-tests.yml</ref><br />
# 點擊 Run workflow。<br />
#* 若修改了[[#產測資|產測資程式]],在 Problem labels to build inputs 輸入[[#題目編號|題目編號]],例如「B」,其他欄位不需重複輸入題號。將會自動建置輸入及輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅修改了[[#標程|標程]],導致僅有輸出會變動,在 Problem labels to build outputs 輸入[[#題目編號|題目編號]],其他欄位不需重複輸入題號。將會自動建置輸出,若測資有變動,亦會自動測試標程。<br />
#* 若僅要重新執行標程測試,在 Problem labels to run solutions 輸入[[#題目編號|題目編號]]。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待測資建置完成。<br />
# 可在對應題目的 tests 資料夾找到建置的測資<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/tests</ref>。標程測試則在 solutions-check.txt<ref>參考連結:https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions-check.txt</ref><br />
<br />
{{reflist-talk}}<br />
<br />
=== 自動建置測資 ===<br />
若產測資程式和標程皆已定稿,可開啟自動建置功能,之後對於相關檔案的修改都會觸發自動建置。刪除 statement/DISABLE_AUTO_BUILD<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/tests/DISABLE_AUTO_BUILD</ref> 即可開啟自動建置測資。<br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=377
CMS
2022-08-18T15:23:40Z
<p>Xiplus:</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編譯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 設定題目 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|-<br />
| Test cases || 測資 || 參見[[#Upload testcases|Upload testcases]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上傳測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}<br />
<br />
== 上傳限制 ==<br />
上傳限制為參賽者上傳程式碼答案的相關限制,通常為連續兩次上傳的間隔時間限制,亦有可能包含總上傳次數的限制。<br />
<br />
上傳限制應根據競賽性質設定,對於[[資訊學科能力競賽校內選拔]],初賽可比照南區賽,複賽比照全國賽。其他競賽可參考國際資訊奧林匹亞競賽(IOI)等重要競賽,以下列出重要競賽的規定以供參考:<br />
<br />
* IOI 2009 ─ 似乎無時間限制,總次數 50 次。<ref>http://www.ioi2009.org/index.jsp?ln=2&id=361</ref><br />
* IOI 2010 ─ 似乎無限制。<ref>https://ioi2010.org/rules.shtml</ref><br />
* IOI 2012 ─ 間隔 1 分鐘,總次數 64 次。<ref>http://www.ioi2012.org/competition/rules/index.html</ref><br />
* IOI 2013-2014 ─ 間隔 1 分鐘,總次數 100 次。<ref>https://www.ioi2013.org/competition/rules/</ref><ref>https://www.ioi2014.org/competition/contest-rules.html</ref><br />
* IOI 2016 ─ 間隔 1 分鐘,競賽最後 15 分鐘解除限制,總次數 100 次。<ref>http://infolymp.ru/juniors/files/IOI2016Rules.pdf</ref><br />
* IOI 2017-2022 ─ 間隔 1 分鐘,競賽最後 15 分鐘解除限制,總次數 50 次。<ref>https://ioi2017.ir/contest/rules/#submitting</ref><ref>https://ioi2018.jp/competition/competition-rules/#submitting</ref><ref>https://ioi2019.az/en-content-14.html#Submitting</ref><ref>https://ioi2020.sg/rules/#submitting</ref><ref>https://ioi2021.sg/rules/#submitting</ref><ref>https://ioi2022.id/competition-rules/</ref><br />
<br />
{{reflist-talk}}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=376
CMS
2022-08-18T14:54:01Z
<p>Xiplus:/* 題目設定 */</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編譯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 設定題目 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|-<br />
| Test cases || 測資 || 參見[[#Upload testcases|Upload testcases]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上傳測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=375
CMS
2022-08-18T14:53:16Z
<p>Xiplus:/* 設定競賽 */</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編譯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 題目設定 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|-<br />
| Test cases || 測資 || 參見[[#Upload testcases|Upload testcases]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上傳測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=374
CMS
2022-08-18T14:52:41Z
<p>Xiplus:/* Upload testcases */</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編輯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 題目設定 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|-<br />
| Test cases || 測資 || 參見[[#Upload testcases|Upload testcases]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上傳測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=373
CMS
2022-08-18T14:51:26Z
<p>Xiplus:/* 題目設定 */</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編輯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 題目設定 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|-<br />
| Test cases || 測資 || 參見[[#Upload testcases|Upload testcases]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上船測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=372
CMS
2022-08-18T14:48:28Z
<p>Xiplus:/* Upload testcases */</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編輯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 題目設定 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上船測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}</div>
Xiplus
https://wiki.tfcis.org/index.php?title=CMS&diff=371
CMS
2022-08-18T14:48:19Z
<p>Xiplus:</p>
<hr />
<div>官方文件:https://cms.readthedocs.io/en/v1.4/<br />
<br />
== 建立競賽 ==<br />
# 點擊 Administration<br />
# 在 Contests 段落,點擊 (create new contest...)<br />
# 在 Name 輸入英文競賽名稱,此欄位不會顯示給參賽者<br />
# 點擊 Submit<br />
<br />
== 設定競賽 ==<br />
以下說明是根據預設設定需要修改的欄位,其餘欄位不需更動。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Description || 中文競賽名稱 || 顯示於競賽介面左上角<br />
|-<br />
| Allowed programming languages<br />
| 參賽者可以使用的程式語言<br />
| 僅勾選以下 4 項,其餘取消勾選<br />
# C++11 / g++<br />
# C++14 / g++<br />
# C++17 / g++<br />
# C11 / gcc<br />
請務必測試每個語言皆能正常編譯<br />
|-<br />
| Allow user tests || 開啟「線上測試」介面,允許參賽者在伺服器上編輯並執行自訂輸入 || 視競賽決定是否勾選<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Start time || 競賽開始時間 || 注意時區為 UTC,為本地時間 -8 小時,建議於準備時期設為未來日期,在競賽開始前才設為正確時間<br />
|-<br />
| End time || 競賽結束時間 || 同上<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 應設為空字串,不對所有題目進行限制,應對個別題目限制<br />
|}<br />
<br />
== 題目設定 ==<br />
如果使用 [[TPS]] 格式,通常匯入後無需在 CMS 管理介面進行設定。以下說明手動新增題目需設定的欄位。<br />
<br />
{| class="wikitable"<br />
|+ Task configuration<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Name<br />
| 題目英文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
|-<br />
| Title<br />
| 題目中文名稱<br />
| 顯示於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
|-<br />
| Feedback level<br />
| 對參賽者顯示完整評測結果<br />
| 設為 Full<br />
* Restricted:僅顯示第一筆非 AC 結果(及前面的所有 AC 結果)<br />
* Full:顯示所有結果<br />
|-<br />
| Token mode || || 設為 Disabled<br />
|-<br />
| Minimum interval between submissions || 上傳時間間隔 || 視比賽而定<br />
|-<br />
| Score mode || 計分模式 || 應設為 Use the sum over each subtask of the best result for that subtask across all submissions (IOI 2017-)<br />
|}<br />
<br />
{| class="wikitable"<br />
|+ Datasets<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Time limit || 時間限制 || 單位為秒<br />
|-<br />
| Memory limit || 記憶體限制 || 單位為 MiB<br />
|-<br />
| Task type || 題目類型 || 通常為 Batch<br />
|-<br />
| Score Type || 計分類型 || 通常為 GroupMin<br />
|-<br />
| Score Parameters || 分數參數 || 參見[[#Score Parameters|Score Parameters]]<br />
|}<br />
<br />
{{reflist-talk}}<br />
<br />
=== Score Parameters ===<br />
分數參數格式為 <syntaxhighlight lang="json" inline>[[m1, t1], [m2, t2], ...]</syntaxhighlight> ,根據你命名測資檔的方式,分為以下兩種格式。<br />
<br />
可參考:https://cms.readthedocs.io/en/v1.4/Score%20types.html#groupmin<br />
<br />
==== 流水號 ====<br />
適用於檔名依序命名為 1, 2, 3...。<br />
<br />
tn 表示依序號使用的測資數量,前 t1 筆測資配分為 m1,接下來 t2 筆測資配分為 m2,以此類推。<br />
<br />
例如 <syntaxhighlight lang="json" inline>[[20, 10], [30, 20], [50, 30]]</syntaxhighlight> 表示:第 1 ~ 10 筆測資 20 分、第 11 ~ 30 筆測資 30 分、第 31 ~ 60 筆測資 50 分。<br />
<br />
==== 依測資點分組 ====<br />
適用於檔名命名為 「a-b」,a 為測資點,b 為該測資點的流水號,例如 1-02 表示第 1 個測資點的第 2 筆測資。<br />
<br />
tn 為一正規表達式,例如 <syntaxhighlight lang="json" inline>[[20, "1-.+"], [30, "2-.+"], [50, "3-.+"]]</syntaxhighlight> 表示:第 1 個測資點 20 分、第 2 個測資點 30 分、第 3 個測資點 50 分。<br />
<br />
如果需要讓該筆子任務的測資直接包含其他子任務,可用正規表達式方式達成。<br />
<br />
=== Upload testcases ===<br />
點擊 Add multiple testcases 後會進到上船測資介面,測資應預先準備於一個資料夾內,建議輸入檔副檔名為 .in,輸出檔副檔名為 .out,並壓縮成 zip 檔。<br />
<br />
{| class="wikitable"<br />
|-<br />
! 欄位 !! 欄位說明 !! 操作說明<br />
|-<br />
| Archive || 壓縮檔 || 選擇壓縮檔<br />
|-<br />
| Public || 是否公開測資點(並非公開測資內容) || 應勾選<br />
|-<br />
| Overwrite existing testcases || 覆蓋相同檔名測資 || 視情況勾選,通常更新測資時需勾選<br />
|-<br />
| Input file names template || 輸入檔命名規則 || 通常為 *.in<br />
|-<br />
| Output file names template || 輸出檔命名規則 || 通常為 *.out<br />
|}<br />
<br />
* Archive <br />
* Public 應勾選<br />
* Overwrite existing testcases 視情況</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=370
題目敘述故事
2022-08-17T15:12:16Z
<p>Xiplus:/* 題本架構 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|507|A. 二分圖匹配(說明圖片位於第 2 頁最上方)<br />
|570|E. 存在X(說明圖片位於本文尾端)<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
{{clear}}<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
{{clear}}<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=369
TPS
2022-08-17T14:57:32Z
<p>Xiplus:/* 註解 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 事前準備 ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 操作方式 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=368
TPS
2022-08-17T14:48:57Z
<p>Xiplus:/* 提示 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 事前準備 ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 操作方式 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
{{TOJ side box<br />
|335|F. 參訪者們<br />
|509|C. Puyo<br />
}}<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|473|A. 好哈快捷鍵<br />
}}<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== 註解 ==<br />
<references/></div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=367
題目敘述故事
2022-08-17T14:43:58Z
<p>Xiplus:/* 一般 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|507|A. 二分圖匹配(說明圖片位於第 2 頁最上方)<br />
|570|E. 存在X(說明圖片位於本文尾端)<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=366
題目敘述故事
2022-08-17T14:41:30Z
<p>Xiplus:/* 插圖 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|570|E. 存在X<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。插圖通常放置於標題下方、本文的最上方。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=365
題目敘述故事
2022-08-17T14:40:30Z
<p>Xiplus:/* 一般 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
{{TOJ side box<br />
|570|E. 存在X<br />
}}<br />
如果題意需要圖片輔助說明,可放在本文尾端(較短的本文)或其他合適地方(較長的本文),如果題目沒有[[#插圖|插圖]],亦可放置在插圖處。<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=TPS&diff=364
TPS
2022-08-17T14:37:13Z
<p>Xiplus:/* 範例輸入及輸出 */</p>
<hr />
<div>TPS(Task Preparation System)是一套可以方便產生題目測試資料以及題本的工具,關於 TPS 可以參考以下的 GitHub Repo:<br />
* TPS Example:https://github.com/TNFSH-Programming-Contest/TPS-example<br />
* IOI 2017 TPS:https://github.com/ioi-2017/tps<br />
<br />
== 資料夾結構 ==<br />
=== 根目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| .github/workflows/ || Github 自動化流程設定檔<br />
|-<br />
| pA/ || [[#題目目錄|題目A]]<br />
|-<br />
| pB/ || [[#題目目錄|題目A]]<br />
|-<br />
| Makefile || [[File:Icon tools.svg|20px]] 匯入 CMS 的指令<br />
|-<br />
| README.md || <br />
|-<br />
| cover.tex || 題本封面<br />
|-<br />
| template.tex || 題本內文模板,不需修改<br />
|}<br />
<br />
=== 題目目錄 ===<br />
{| class="wikitable"<br />
|-<br />
! 資料夾或檔案 !! 說明<br />
|-<br />
| [{{tps sample link}}/pA/attachments/ attachments/] || CMS 題目敘述頁的附件,通常僅會在第一題的附件放置合併題本。<br />
|-<br />
| [{{tps sample link}}/pB/gen/ gen/] || [[#產測資|產測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/scripts/ scripts/] || TPS scripts,不需修改<br />
|-<br />
| [{{tps sample link}}/pB/solution/ solution/] || [[#標程|標程]]<br />
|-<br />
| [{{tps sample link}}/pB/statement/ statement/] || [[#題目敘述|題目敘述]]<br />
|-<br />
| [{{tps sample link}}/pB/tests/ tests/] || 測資檔<br />
|-<br />
| [{{tps sample link}}/pB/validator/ validator/] || [[#驗測資程式|驗測資程式]]<br />
|-<br />
| [{{tps sample link}}/pB/problem.json problem.json] || [[#競賽名稱|競賽名稱]]、[[#題目名稱|題目名稱]]、[[#題目英文名稱|題目英文名稱]]、[[#題目編號|題目編號]]、[[#記憶體限制|記憶體限制]]、[[#時間限制|時間限制]]<br />
|-<br />
| [{{tps sample link}}/pB/solutions-check.txt solutions-check.txt] || 所有標程的執行結果報告<br />
|-<br />
| [{{tps sample link}}/pB/solutions.json solutions.json] || [[#標程|標程]]、[[#產測資|產測資]]指定的標程<br />
|-<br />
| [{{tps sample link}}/pB/subtasks.json subtasks.json] || [[#子任務|子任務]]、使用的[[#驗測資程式|驗測資程式]]<br />
|}<br />
<br />
{{Memo|本頁面主要使用 TNFSH-Programming-Contest/cms-environment-testing-problem<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem</ref> 的 pB<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB</ref> 作為範本。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 事前準備 ==<br />
=== 建立GitHub Repo ===<br />
# 進入 tps-starter。<ref>https://github.com/TNFSH-Programming-Contest/tps-starter</ref><br />
# 點擊 Use this template。<ref>直接連結:https://github.com/TNFSH-Programming-Contest/tps-starter/generate</ref><br />
# 填寫Repo資訊<br />
#* Repository name 填入競賽英文名,例如「cms-environment-testing-problem」。<br />
#* Description 填入競賽中文名,例如「CMS環境測試題目通用版」。<br />
#* [[File:OOjs UI icon alert-destructive.svg|20px]] '''注意:'''可見度必須選擇 '''Private'''。<br />
#* 點擊 Create repository from template。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 建立題目資料夾 ===<br />
此操作在每個競賽通常僅需執行 1 次。<br />
# 進入由 tps-starter 建立的 GitHub repo。<br />
# 點擊 Actions。<br />
# 在 Workflows 段落,點擊 New problem。<ref>參考連結:https://github.com/TNFSH-Programming-Contest/TPS-example/actions/workflows/new-problem.yml</ref><br />
# 點擊 Run workflow,在 How many problems in this contest? 輸入要建立的題目數量。<br />
#* 如果已有 3 題,要再新增 1 題,直接輸入 4 即可,已建立的目錄會直接被略過。<br />
# 點擊藍色 Run workflow 按鈕。<br />
# 等待題目目錄建立完成,約 1 分鐘。<br />
<br />
{{reflist-talk}}<br />
<br />
== 操作方式 ==<br />
[[File:Icon tools.svg|20px]] 以下有此標誌的說明需要 CMS 系統管理員操作,出題者可忽略此說明。<br />
<br />
=== 競賽名稱 ===<br />
競賽名稱使用於:<br />
# CMS 參賽介面左上角。<br />
# 題本封面第一行。<br />
# 題本內文各頁的左上角。<br />
<br />
需寫入於:(範例為「CMS環境測試題目通用版 v1.1」)<br />
# cover.tex。<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/cover.tex</ref><br />
# 各題目 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 contest_name 欄位。<br />
# [[File:Icon tools.svg|20px]] CMS 管理系統的 Description 欄位。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目名稱 ===<br />
題目名稱使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述頁面。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 title 欄位,範例為「Piñata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目英文名稱 ===<br />
題目英文名稱應足以讓所有命題人員識別個別題目即可,通常取自於中文題目名稱,並盡量僅使用一個英文詞,首字大寫,若需要兩個英文詞以上,則使用[[zhwiki:駝峰式大小寫|PascalCase]]。使用於:<br />
# CMS 競賽概況的題目列表。<br />
# CMS 題目敘述。<br />
# CMS 系統內部用來識別題目的 [[zhwiki:主鍵|Primary key]]。<br />
#* [[File:Icon tools.svg|20px]] 由於同一 CMS 系統上的名稱無法重複,若與其他競賽題目衝突<ref>https://github.com/cms-dev/cms/issues/765</ref>,建議加上競賽名稱的英文縮寫作為前綴(例如「2022P-」)。<br />
# 可能作為 GitHub repo 內的題目資料夾名稱。<br />
<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 name 欄位,範例為「Pinata」。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目編號 ===<br />
題目編號為 A, B, C... 的流水號,在決定題目順序後才會確定,使用於:(範例為「B」)<br />
# CMS 競賽概況的題目列表。<br />
# 題目標題(第一頁第一行)。<br />
# 該題目各頁右上角。<br />
# 該題目各頁頁碼處。<br />
<br />
=== 記憶體限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 memory_limit 欄位,單位為MB,範例為「512」MB。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 時間限制 ===<br />
需寫入於 problem.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/problem.json</ref> 的 time_limit 欄位,單位為秒,範例為「1.0」秒。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 標程 ===<br />
AC code(官方解法、標程等)需放置在 solution<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution</ref> 資料夾內,檔名無限制。同時將該檔名寫入 solutions.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/solutions.json</ref> ,格式請參照範本,verdict 必須標記為 model_solution,範例檔名為「ac.cpp」<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/solution/ac.cpp</ref>。<br />
<br />
其他 AC code 亦按照前述方式操作,verdict 必須標記為 correct。<br />
<br />
其他類型的錯誤解法亦按照前述方式操作,verdict 標記方式請參考官方說明<ref>https://github.com/ioi-2017/tps/tree/master/docs#solutionsjson</ref>及 tps script<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/93cff7e64a43f57450b26568194432e7b662be38/default/scripts/internal/invoke.py#L18</ref>。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 產測資 ===<br />
TPS 產測資方式與 Codeforces polygon 相同。測資可以使用手產測資檔案,亦可由程式亂數產生,亦可混合兩者。<br />
<br />
==== 手產測資檔 ====<br />
{{Memo|'''最佳實踐:'''<br />
# 僅在範例測資和 [[:zhwiki:en:Edge case|edge case]] 使用手產測資檔,其他使用產測程式。<br />
# 在 gen/manual 保存與題本相同的範例測資。<br />
|}}<br />
<br />
手產測資檔應放置在 gen/manual 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen/manual</ref>內,檔名無限制,但建議副檔名為 .in。<br />
<br />
本範例包含一個固定測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref> 作為範例測資。<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資程式 ====<br />
{{Memo|'''重要:'''產測資程式必須<br />
# 使用命令列參數讀入測資組及測資點<ref>[https://en.cppreference.com/w/cpp/language/main_function Main function - cppreference.com]</ref><ref>[https://stackoverflow.com/questions/3024197/what-does-int-argc-char-argv-mean c++ - What does int argc, char *argv&#x5B;&#x5D; mean? - Stack Overflow]</ref>。<br />
# 使用[[zhwiki:stdout|標準輸出(stdout)]],不可直接寫入檔案。<br />
# 執行一次僅輸出一筆測資。<br />
# 使用 testlib.h<ref>[https://codeforces.com/blog/entry/18291 Generators with testlib.h]</ref> 等設定亂數種子的方式,使得每次產生的測資都是相同的。<br />
|inline:notice}}<br />
<br />
產測資程式應放置在 gen 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/gen</ref>內,檔名無限制。<br />
<br />
以下說明請配合範例檔案 gen/gen.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/gen.cpp</ref>。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>#include "testlib.h"</syntaxhighlight> 引入 testlib 函式庫。<br />
<br />
main 函數務必寫成 <syntaxhighlight lang="c++" inline>int main(int argc, char* argv[])</syntaxhighlight> 來接收命令列參數。<br />
<br />
在 main 函數的第一行使用 <syntaxhighlight lang="c++" inline>registerGen(argc, argv, 1);</syntaxhighlight> 將命令列參數作為亂數種子。<br />
<br />
命令列參數會保存在 <syntaxhighlight lang="c++" inline>argv</syntaxhighlight> 內,可將其保存在 string 內: <syntaxhighlight lang="c++" inline>string task = argv[1];</syntaxhighlight>,或是使用 atoi<ref>https://en.cppreference.com/w/cpp/string/byte/atoi</ref> 等函數轉換為整數。例如範例中第一個參數用來判斷是第幾組測資,將其轉換為 <syntaxhighlight lang="c++" inline>int taskN</syntaxhighlight> 用於判斷。若為第一筆測資,測資範圍則為 87,若為其他測資,測資範圍則為 10^9。<br />
<br />
使用 <syntaxhighlight lang="c++" inline>rnd.next(-maxN, maxN)</syntaxhighlight> 來隨機產生範圍在 -maxN 到 maxN 之間的整數,保存在變數上用於之後輸出。<br />
<br />
最後將產生的測資輸出。<br />
<br />
{{Memo}} 由於 cout 中執行順序屬未定義行為,請勿將多個 rnd.next 合併在一個 cout 中使用,請分開 cout 或事先保存在變數上。<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}} <br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " " << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{N}} 未定義行為<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
cout << rnd.next (1, n) << " ";<br />
cout << rnd.next (1, n) << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="c++"><br />
int a = rnd.next (1, n), b = rnd.next (1, n);<br />
cout << a << " " << b << endl;<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
完成產測資程式後,編譯成檔名為 gen 的執行檔(在 Windows 上的 gen.exe),在命令列使用:<br />
* <code>gen 1</code> 會隨機產生 4 個 -87 ~ 87 之間的數字(格式參見題目敘述)<br />
* <code>gen 2</code> 會隨機產生 4 個 -10^9 ~ 10^9 之間的數字<br />
<br />
{{reflist-talk}}<br />
<br />
==== 產測資指令 ====<br />
產測資指令應放置在 gen/data<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/data</ref>,以下說明請配合範例。<br />
<br />
每一個測資點以 @subtask 接測資點代號為開頭,這個測資點代號亦會使用在[[#子任務配分|子任務配分]]。<br />
<br />
接下來每個測資點可以有多筆測資,每筆測資可以使用手產測資檔,也可使用產測資程式。<br />
* 使用手產測資檔則為 manual 接續放在 gen/manual 資料夾內的測資檔名。<br />
* 使用產測資程式則為呼叫在命令列中的指令。<br />
<br />
範例中第一行為 @subtask samples 為範例測資(samples 為固定名稱不可更改),包含一個手動測資檔 sample-01.in<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/gen/manual/sample-01.in</ref>。<br />
{{Memo|'''重要:'''將範例測資作為配分為 0 的第一筆測資點,名稱為 samples。|}}<br />
<br />
範例中除了範例測資外,共有 2 個測資點,名稱分別為 small 跟 all。兩個測資點都包含 5 筆自動測資。<br />
<br />
{{Memo}} 如果呼叫產測程式,但在指令中輸入了兩行一模一樣的內容,那麼這兩個測資就會相同(在設定亂數種子的情況下)。<br />
<br />
{| class="wikitable"<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1<br />
gen 1<br />
gen 1<br />
</syntaxhighlight><br />
| {{N}} 會產生 3 筆相同測資<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 1<br />
gen 1 2<br />
gen 1 3<br />
</syntaxhighlight><br />
| {{Y}}<br />
|-<br />
| <syntaxhighlight lang="text"><br />
@subtask small<br />
gen 1 pewfw<br />
gen 1 qrewx<br />
gen 1 xckxk<br />
</syntaxhighlight><br />
| {{Y}}<br />
|}<br />
<br />
因此通常會在後面放上隨機文字作為亂數種子的一部分,亦可透過更換亂數種子來重新產生測資,隨機文字可使用線上工具<ref>例如 [https://www.random.org/strings/ Random String Generator]</ref>產生。<br />
<br />
{{Memo|'''小技巧:'''<br />
# 透過命令列參數直接控制測資範圍,就不需要在產測資程式碼內判斷測資點。<br />
# 發現不良的測資時,透過修改命令列參數的隨機文字來得到一筆新的隨機測資。<br />
# 若需要 edge case,使用手產測資檔。<br />
|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 驗測資程式 ===<br />
{{Quote<br />
| 如果你寫了一個程式解題的問題,並準備好了測試資料,那麼你將可能會遇到一個恐怖的經驗:測試資料是無效的!(即測試資料並未符合題目所規定的限制),例如超過了範圍上限、你的圖實際上沒有連通、或是你的圖不是一棵樹……你很可能會有這種經驗,就算是有經驗的出題者也可能有時會出錯(知名案例像是 ACM ICPC World final 2007)。<br />
| 翻譯自 [https://codeforces.com/blog/entry/18426 Codeforces 上對於 Validator 的引言]。<br />
}}<br />
{{Memo|'''最佳實踐:'''撰寫驗測資程式來自動檢查測資範圍及其他條件是否有符合題目的規定,避免測資範圍錯誤。|}}<br />
<br />
驗測資程式(又稱 validator)應該放置在 validator 資料夾<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/tree/main/pB/validator</ref>內,檔名無限制,並將檔名寫入 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 的 global_validators 或 subtasks 的 validators。<br />
<br />
本範例包含 2 個 validator。<br />
<br />
validator.cpp <ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator.cpp</ref> 用來驗證所有測資的範圍是否在 -10^9 ~ 10^9 內,故在 subtasks.json<ref name="subtasks">https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref> 中設為 global_validators。<br />
<br />
validator-small.cpp<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/validator/validator-small.cpp</ref> 僅用來測試第 2 筆測資(index = 1)範圍是否在 -87 ~ 87,在 subtasks.json 中設定為 測資 small 的 validators。<br />
<br />
除了檢查範圍以外,readInt 等函數會回傳其數值,可以保存到變數上作進一步檢查,例如檢查陣列數值皆相異,檢查是否是圖、樹或其他資料結構。<br />
<br />
更多資訊請參見 Codeforces 上的說明<ref>[https://codeforces.com/blog/entry/18426 Validators with testlib.h - Codeforces]</ref>。<br />
<br />
{{Memo|'''小提示:'''驗測資程式僅檢查與解法無關的輸入資料限制,檢查是否 TLE、得部分分數屬於[[#標程|標程]]的範圍。|}}<br />
<br />
{{reflist-talk}}<br />
<br />
=== 子任務 ===<br />
子任務設定於 subtasks.json<ref>https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/subtasks.json</ref>,包含各子任務的配分、文字描述、[[#驗測資程式|驗測資程式]]。以下說明請參考範例。<br />
<br />
subtasks.json 最外層包含兩個 key:<br />
* global_validators:在所有測資使用的[[#驗測資程式|驗測資程式]]。<br />
* subtasks:包含所有測資點。<br />
<br />
subtasks 是一個 key-value pairs,key 與[[#產測資指令|產測資指令]]中設定的相同。value 包含以下 key-value pairs:<br />
* index:流水號,出現在題本內的順序,從 0 開始;samples 必為 0。<br />
* score:子任務分數;samples 必為 0。<br />
* text:子任務描述,使用在題目描述內。<br />
* validators:僅在該子任務使用的[[#驗測資程式|驗測資程式]]。<br />
<br />
{{reflist-talk}}<br />
<br />
=== 題目敘述 ===<br />
題本檔案放置於 [https://github.com/TNFSH-Programming-Contest/cms-environment-testing-problem/blob/main/pB/statement/index.md statement/index.md]。使用 [[zhwiki:Markdown|Markdown]] 及 [[zhwiki:XeTeX|XeTeX]] 語法。<br />
<br />
結構由上到下依序為:<br />
# [[#題目圖片|題目圖片]]<br />
# [[#題目本文|題目本文]]<br />
# [[#輸入及輸出說明|輸入(說明)]]<br />
# [[#輸入及輸出說明|輸出(說明)]]<br />
# [[#輸入限制|輸入限制]]<br />
# [[#子任務說明|子任務]]<br />
# [[#範例輸入及輸出|範例輸入]]<br />
# [[#範例輸入及輸出|範例輸出]]<br />
# [[#提示|提示]]<br />
<br />
==== 題目圖片 ====<br />
參見[[題目敘述故事#插圖]]。<br />
<br />
==== 題目本文 ====<br />
參見[[題目敘述故事]]。<br />
<br />
==== 輸入及輸出說明 ====<br />
輸入輸出說明必須明確說明參賽者要遵守的格式。<br />
<br />
應該以一行敘述測資中的一行所代表的資料,例如:<br />
* 第一行有 1 個整數,代表接下來的測資數量。<br />
* 第一行有 2 個整數,代表初始座標。<br />
<br />
如果需要在其他地方(輸入說明的其他行、輸入限制、題目本文等)提到該變數,應賦予變數代號,例如:<br />
* 第一行有 2 個整數 <math>V, E</math>,<math>V</math> 代表點的數量,<math>E</math> 代表邊的數量。<br />
* 第一行有 1 個整數 <math>N</math>,代表有 <math>N</math> 個人。...(換行)...接下來有 <math>N</math> 行,每一行有 1 個整數代表該人的分數。<br />
{{Memo|'''注意:'''同一個變數代號必須在該題目的任何地方皆相同,大小寫也必須相同。|}}<br />
<br />
==== 輸入限制 ====<br />
輸入限制用來告知參賽者測資的數值範圍限制,<br />
{| class="wikitable"<br />
|-<br />
! 原始碼 !! 顯示結果<br />
|-<br />
| <syntaxhighlight lang="markdown"><br />
- $1 \leq N \leq 100$<br />
- $1 \leq M \leq N$<br />
- $Y - X$ 必定為 2 個倍數<br />
- 若 $A = 1$,則 $B > 0$<br />
</syntaxhighlight><br />
|<br />
* <math>1 \leq N \leq 100</math><br />
* <math>1 \leq M \leq N</math><br />
* <math>Y - X</math> 必定為 2 個倍數<br />
* 若 <math>A = 1</math>,則 <math>B > 0</math><br />
|}<br />
<br />
==== 子任務說明 ====<br />
參見[[#子任務|子任務]]的操作,即會自動顯示於題本中。<br />
<br />
==== 範例輸入及輸出 ====<br />
範例輸入輸出必須與[[#產測資|產測資]]中設定的範例測資相同。<br />
<br />
{{TOJ side box<br />
|628|B. 國中會考分<br />
}}<br />
如果有多筆範例測資,標題應改命名為「範例輸入1、範例輸出1、範例輸入2、範例輸出2」等。<br />
{{clear}}<br />
<br />
{{TOJ side box<br />
|631|E. 蓋歐格(單個範例附說明)<br />
|632|F. 最小生成數(多個範例,僅有 1 個範例有說明)<br />
|637|D. 本田小狼(有圖片的範例說明)<br />
}}<br />
如果有需要說明測資,可加上「範例說明」章節,詳細說明範例測資中的意義,亦可附圖說明。<br />
<br />
{| class="wikitable"<br />
|-<br />
| style="vertical-align: top" |<br />
* 範例輸入<br />
* 範例輸出<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例輸入2<br />
* 範例輸出2<br />
| style="vertical-align: top" |<br />
* 範例輸入1<br />
* 範例輸出1<br />
* 範例說明1<br />
* 範例輸入2<br />
* 範例輸出2<br />
|}<br />
<br />
==== 提示 ====<br />
如有需要,可以提供一些額外提示。如果內容為解題必須的,不應撰寫於提示,應寫於本文中。<br />
<br />
亦可撰寫與解題毫無幫助,但與題目故事相關的小知識。<br />
<br />
== 註解 ==<br />
<references/></div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=363
題目敘述故事
2022-08-17T14:28:37Z
<p>Xiplus:/* 故事設定 */</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 資料結構與故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=%E9%A1%8C%E7%9B%AE%E6%95%98%E8%BF%B0%E6%95%85%E4%BA%8B&diff=362
題目敘述故事
2022-08-17T14:26:56Z
<p>Xiplus:</p>
<hr />
<div>使用故事來包裝題目敘述,可以幫助參賽者更容易了解題目,又或是考驗參賽者的閱讀理解能力。<br />
<br />
== 目的及優點 ==<br />
題目敘述通常會編寫故事來讓參賽者融入該問題的情境,以更好地了解題目所要問的內容。<br />
<br />
=== 範例1 ===<br />
{{TOJ side box|630|D. 花子一口吞}}<br />
110 學年度資訊學科能力競賽臺南一中校內初選 D. 花子一口吞<br />
; 裸題敘(原始題敘)<br />
: 給長度 N 的正整數數列 A,求一區間使「區間和 mod K」最大。<br />
; 包裝後題敘<br />
: 有容量不同的飼料盆排成一列,要把一個區間的飼料全部吃完,吃的時候會把嘴巴塞滿才吞下去,詢問最後一口剩餘在嘴中的飼料數量。<br />
<br />
以上題目若僅使用裸題敘,參賽者可能就難以理解,可能會有「數列?區間?為什麼要 mod K?」等疑惑,但透過故事包裝的方式,讓題目變成現實生活中可能發生的情境,先透過故事引導參賽者融入情境,這時候再提出問題,便很容易理解問題是什麼。一些演算法原本就能解決現實生活中的問題,因此以實際會遇到的情境去包裝題目問題就能讓題目變得很易懂。<br />
<br />
=== 範例2 ===<br />
2008 網際網路程式設計全國大賽高中組決賽 B. 幼稚國王去旅行<br />
; 裸題敘(原始題敘)<br />
: 輸出 1 就是答案。<br />
; 包裝後題敘<br />
: 參見 [https://contest.cc.ntu.edu.tw/npsc2008/2008sen_final.pdf 題本]。<br />
相反的情況是將簡單的題目包裝起來,測驗參賽者的閱讀理解能力。另外對於 Hello World 或是 A+B 等題目,包裝一點故事才不會讓題敘過短。<br />
<br />
=== 總結 ===<br />
總結,使用故事來包裝題目敘述可以:<br />
# 更容易理解題目。<br />
# 純粹測試閱讀能力。<br />
# 讓題目有趣一些。<br />
# 讓不會解題的參賽者在競賽中不至於那麼無聊。<br />
# 讓出題者對喜愛的作品置入性行銷。<br />
<br />
== 題本架構 ==<br />
<br />
=== 一般 ===<br />
{{TOJ side box<br />
|629|C. GAMAGAMA<br />
|630|D. 花子一口吞<br />
|637|D. 本田小狼<br />
}}<br />
能使用故事來包裝的題目,題目本文的架構通常如下:<br />
<br />
一開始用少數幾句話介紹世界觀,通常與所參考的作品相同,這邊的介紹對解題通常沒有幫助,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館面臨即將停業的危機<br />
* {{TOJ|630}} ─ 自稱為半龍人的貪吃少女 — 花子,實際上卻是魔界四大公爵-龍族法夫納家的下任家主!<br />
* {{TOJ|637}} ─ 今天小熊騎著本田小狼 50 兜風<br />
<br />
進一步介紹故事劇情,這裡就會提到測資中會出現的設定,例如城市與道路的數量,例如:<br />
* {{TOJ|629}} ─ GAMAGAMA 水族館有兩條觀察大型水族箱的海底隧道...<br />
* {{TOJ|630}} ─ 她會選定某盆飼料開始一顆顆往嘴巴裡吃,一但到達嘴巴能裝的最多數量 K,就會一口吞下!<br />
* {{TOJ|637}} ─ 如果將所有的景點、店家等等都當作是一個節點,並且依序將節點從 1~n 編號,制高點編號為 1<br />
<br />
最後提出題目真正要詢問的問題,例如:<br />
* {{TOJ|629}} ─ 為了控制不要讓積分過度膨脹,必須先進行模擬<br />
* {{TOJ|630}} ─ 請幫助花子找到留下最多飼料當作點心的方法<br />
* {{TOJ|637}} ─ 請問小熊可以選擇的地點有多少個?<br />
<br />
=== 無法包裝的題目 ===<br />
但還是有一些題目實在不會在現實生活中遇到,這時候只好勉為其難使用爛招,也就是在題目敘述寫一些無關緊要的描述,最後再直白的亮出問題。<br />
<br />
==== Hello World ====<br />
{{TOJ side box<br />
|547|0. Hello World<br />
|618|A. 比賽須知<br />
|633|G. 簡單易懂的現代魔法<br />
}}<br />
對於直接輸出 Hello World 的題目,實在沒有什麼劇情可言,通常做法是隨便介紹一下 Hello World 的由來,然後在輸出說明要求輸出 Hello World 而已。<br />
<br />
==== 數學題目 ====<br />
{{Quote<br />
|題目:請用「XX」造句。<br />
<br />
答案:「今天老師出了一個題目,讓我們用XX造句。」<br />
|造句的爛招<br />
}}<br />
<br />
{{TOJ side box<br />
|571|F. 大家來找碴<br />
|638|E. 遞迴呀遞迴<br />
}}<br />
如同以上造句的通用解答,實際上對於所有題目也可以使用以下的通用敘述:<br />
<br />
{{Quote<br />
|...(毫無意義的故事,通常與教室、老師有關)...<br />
<br />
老師問了一個問題,請解出 XXXXX(題目本身)。<br />
|數學題目的題目本文<br />
}}<br />
<br />
== 插圖 ==<br />
題目插圖通常與題目本文中使用的故事相關,來提高參賽者解題興趣,例如使用動畫設定作為背景故事則會使用該動畫的截圖。無論有無插圖都不影響題意理解,故插圖不是必須的。<br />
<br />
若使用[[TPS]]題本格式<ref>https://github.com/TNFSH-Programming-Contest/tps-task-templates/blob/main/default/statement/index.md</ref>,可使用以下語法:<br />
<syntaxhighlight lang="text"><br />
\begin{figure}[h]<br />
\centering<br />
\includegraphics[width=12cm]{FILENAME.jpg}<br />
\caption{圖片說明,出自動畫《動畫名稱》}<br />
\end{figure}<br />
</syntaxhighlight><br />
<br />
{{TOJ side box|571|F. 大家來找碴}}<br />
建議可使用有[[zhwiki:創用CC授權條款|創用CC]]等授權條款,或其他明確向公眾授權的圖片,例如吉卜力工作室的動畫劇照<ref>https://www.ghibli.jp/info/013409/</ref>等。<br />
{{clear}}<br />
<br />
{{Legal}}<br />
<br />
引用受著作權保護的圖片將依著作權法<ref>https://law.moj.gov.tw/LawClass/LawAll.aspx?PCode=J0070017</ref>第 52 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=52</ref>以教學為目的主張[[zhwiki:合理使用|合理使用]]。唯應依同法第 64 條<ref>https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=64</ref>標明出處,在圖片說明以「出自動畫《動畫名稱》」等字樣標示。另根據同法第 65 條<ref name="copyright-act-65">https://law.moj.gov.tw/LawClass/LawSingle.aspx?pcode=J0070017&flno=65</ref>第 2 款第 3 項,縮小圖片解析度,建議在 12cm 的顯示效果下將圖片寬度壓縮至 640 px(16:9 的圖片高度為 360px)。<br />
<br />
<div style="float: right;"><br />
{{TOJ side box<br />
|330|A. Piñata<br />
|331|B. 尼莫西妮<br />
|332|C. 棋盤<br />
|333|D. 畢業<br />
|334|E. 蛋糕<br />
|335|F. 參訪者們<br />
|336|G. 禮物<br />
}}<br />
</div><br />
<div style="float: right;"><br />
[[檔案:Request permission for K.R.T. Girls.png|200px|縮圖|左|取得授權範例,第四屆大臺南高一生程式設計排名賽]]<br />
</div><br />
如果可行,應嘗試向著作權人取得授權(如右圖),依著作權法第 65 條<ref name="copyright-act-65"/>第 3 項確認合理使用範圍,例如第四屆大臺南高一生程式設計排名賽所使用的圖片。<br />
{{clear}}<br />
<br />
{{reflist-talk}}<br />
<br />
== 故事設定 ==<br />
=== 求餘數 ===<br />
{{TOJ side box<br />
|630|D. 花子一口吞<br />
}}<br />
除法的求餘數可以轉換成多次的減法,例如:<br />
# 使用容量為 K 的水瓢從水缸舀水直到無法盛滿水瓢,問最後剩餘的水量。<br />
<br />
若僅是答案過大而需要取餘數輸出,可以直接寫在輸出說明,不一定要作為題敘的一部分。<br />
<br />
=== 圖 ===<br />
{{TOJ side box<br />
|568|C. ChamJam<br />
}}<br />
圖論問題通常可以轉換為:<br />
# 城市與相連的道路。<br />
# 車站與相連的鐵路。<br />
<br />
==== 有向無環圖 ====<br />
{{TOJ side box<br />
|569|D. 露營<br />
}}<br />
有向無環圖可拆成「有向」和「無環」兩個性質。「有向」可簡單地描述為單向道即可。「無環」則可以在題目中暗示說不會走到重複的點。<br />
<br />
=== 樹 ===<br />
{{TOJ side box<br />
|563|C. 車站<br />
}}<br />
樹仍可以轉換為道路或鐵路,但加上「因為資源有限,所以能讓任兩個城市或車站連通即可」的設定。<br />
<br />
==== 最小生成樹 ====<br />
最小生成樹通常用於要建立道路相連多個城市,使得所有城市連通,權重為該條道路的建設成本,目標為總建設成本最低。<br />
<br />
=== 有根樹 ===<br />
{{TOJ side box<br />
|637|D. 本田小狼<br />
}}<br />
有根樹可以轉換為根節點位於山頂,邊為往山下的道路。<br />
<br />
== 故事題材 ==<br />
故事通常是由編寫者挑選自己熟悉的作品,內容包含日本動畫、遊戲、VTuber等等題材。並且可以在題敘中進行置入性行銷,推薦自己喜愛的作品。<br />
<br />
=== 使用日本動畫的題目 ===<br />
{| class="wikitable sortable"<br />
|-<br />
! 動畫季別 !!動畫名稱 !! 題目 !! 備註<br />
|-<br />
<!-- <br />
{{story-anime-row||||||}}<br />
--><br />
{{story-anime-row|2017|7|Princess Principal|400|B. 羅馬數字|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|庫洛魔法使:透明牌篇|401|C. 封印解除|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2018|1|爆肝工程師的異世界狂想曲|402|D. 咒文詠唱|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2017|10|少女終末旅行|403|E. 旅行問題|2018臺南一中資訊社寒訓練習賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|507|A. 二分圖匹配|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|508|B. 完美河道|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2020|1|戀愛中的小行星|509|C. Puyo|2020臺南一中校內程式設計大賽}}<br />
{{story-anime-row|2019|9|HELLO WORLD|547|0. Hello World|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|7|魔王學院的不適任者~史上最強的魔王始祖,轉生就讀子孫們的學校~|548|A. 阿諾斯·波魯迪戈烏多|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2016|1|為美好的世界獻上祝福!|553|F. 更改咒語|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|4|輝夜姬想讓人告白~天才們的戀愛頭腦戰~|anime=輝夜姬想讓人告白~天才們的戀愛頭腦戰~第2季|554|G. 石上真男人|第七屆國中生程設營練習賽}}<br />
{{story-anime-row|2020|2|哥布林殺手|anime=哥布林殺手:GOBLIN'S CROWN|555|A. 哥布林|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|556|B. 舞會|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1|怕痛的我,把防禦力點滿就對了|564|D. 大楓樹|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|1||anime=緣結熊本|565|E. 熊本|109學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|10|熊熊勇闖異世界|566|A. 熊熊|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|7|Lapis Re:LiGHTs|567|B. LiGHTs|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|神推偶像登上武道館我就死而無憾|568|C. ChamJam|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2020|1|搖曳露營△|anime=房間露營△|569|D. 露營|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2017|1|幼女戰記|570|E. 存在X|109學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|1|轉生成蜘蛛又怎樣!|579|pA - 蜘蛛|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4||anime=壽司大相撲|581|pB - 壽司|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|Vivy -Fluorite Eye's Song-|582|pC - Vivy|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|持續狩獵史萊姆三百年,不知不覺就練到LV MAX|583|pD - Slime|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|4|關於我轉生變成史萊姆這檔事|anime=轉生史萊姆日記 關於我轉生變成史萊姆這檔事|584|pE - 種田|SCIST 第一屆 演算法季後賽}}<br />
{{story-anime-row|2021|7|陰晴不定的體操哥哥|627|A. ABC體操|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2020|7|果然我的青春戀愛喜劇搞錯了。 (動畫)|anime=果然我的青春戀愛喜劇搞錯了。完|628|B. 國中會考分發|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|白沙的Aquatope|629|C. GAMAGAMA|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2019|10|萌獸寵物店|630|D. 花子一口吞|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|關於我轉生變成史萊姆這檔事|anime=關於我轉生變成史萊姆這檔事第2期第2部分|631|E. 蓋歐格|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2021|7|Love Live! Superstar!!|632|F. 最小生成數|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2009|7|簡單易懂的現代魔法|633|G. 簡單易懂的現代魔法|110學年度資訊學科能力競賽臺南一中校內初選}}<br />
{{story-anime-row|2018|10|JoJo的奇妙冒險_(電視動畫)|anime=JoJo的奇妙冒險·第四部·不滅鑽石|634|A. 吉良吉影想平靜地過日子|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|7|我們的重製人生|635|B. 學測分發|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2019|8|為美好的世界獻上祝福!紅傳說|636|C. 為美好的地牢獻上爆擊|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|2021|4|本田小狼與我|637|D. 本田小狼|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
{{story-anime-row|1996|4|玩偶遊戲|638|E. 遞迴呀遞迴|110學年度資訊學科能力競賽臺南一中校內複選}}<br />
|}<br />
<br />
=== 使用《{{zhwiki|愛麗絲與藏六}}》的題目 ===<br />
* 106學年度台南一中資訊學科能力競賽校內初選<br />
** {{TOJ|373}} - A.實驗場<br />
** {{TOJ|374}} - B.飢餓的Sana<br />
** {{TOJ|375}} - C.餐桌禮儀<br />
** {{TOJ|376}} - D.綁架<br />
** {{TOJ|377}} - E.奪回作戰<br />
** {{TOJ|378}} - F.避難<br />
<br />
=== 使用《{{zhwiki|高捷少女}}》的題目 ===<br />
* 第四屆大臺南高一生程式設計排名賽<br />
** {{TOJ|330}} - A. Piñata<br />
** {{TOJ|331}} - B. 尼莫西妮<br />
** {{TOJ|332}} - C. 棋盤<br />
** {{TOJ|333}} - D. 畢業<br />
** {{TOJ|334}} - E. 蛋糕<br />
** {{TOJ|335}} - F. 參訪者們<br />
** {{TOJ|336}} - G. 禮物<br />
* {{TOJ|399}} - A. 大數運算(2018臺南一中資訊社寒訓練習賽)<br />
<br />
=== 使用《{{zhwiki|海綿寶寶}}》的題目 ===<br />
* 107學年度國際資訊奧林匹亞研習營初選臺南一中校內選拔<br />
** {{TOJ|461}} - A. 海綿寶寶的時鐘<br />
** {{TOJ|462}} - B. 海綿寶寶捉水母<br />
** {{TOJ|463}} - C. 我的酸黃瓜呢<br />
** {{TOJ|464}} - D. 找樂子就是要燒掉整個城製造出大大的炸彈<br />
** {{TOJ|465}} - E. 打屁屁大隊<br />
** {{TOJ|466}} - F. 升天電梯<br />
* 2020臺南一中校內程式設計大賽<br />
** {{TOJ|510}} - D. 公平洗牌<br />
** {{TOJ|511}} - E. 野海熊防護圈<br />
** {{TOJ|512}} - F. 樓層交換</div>
Xiplus
https://wiki.tfcis.org/index.php?title=Template:TOJ_side_box&diff=361
Template:TOJ side box
2022-08-17T14:20:17Z
<p>Xiplus:</p>
<hr />
<div>{{Side box<br />
|above = 可參考 TOJ 的題目<br />
|text = <ul style="list-style-type:disc; margin-left: 20px;"><br />
{{#if:{{{1|<noinclude>1</noinclude>}}}|<li>[[toj:{{{1|<noinclude>630</noinclude>}}}|{{{1|<noinclude>630</noinclude>}}}]] {{#if:{{{2|}}}|─ {{{2}}} }}</li><br />
}}{{#if:{{{3|}}}|<li>[[toj:{{{3|}}}|{{{3|}}}]] {{#if:{{{4|}}}|─ {{{4}}} }}</li><br />
}}{{#if:{{{5|}}}|<li>[[toj:{{{5|}}}|{{{5|}}}]] {{#if:{{{6|}}}|─ {{{6}}} }}</li><br />
}}{{#if:{{{7|}}}|<li>[[toj:{{{7|}}}|{{{7|}}}]] {{#if:{{{8|}}}|─ {{{8}}} }}</li><br />
}}{{#if:{{{9|}}}|<li>[[toj:{{{9|}}}|{{{9|}}}]] {{#if:{{{10|}}}|─ {{{10}}} }}</li><br />
}}{{#if:{{{11|}}}|<li>[[toj:{{{11|}}}|{{{11|}}}]] {{#if:{{{12|}}}|─ {{{12}}} }}</li><br />
}}{{#if:{{{13|}}}|<li>[[toj:{{{13|}}}|{{{13|}}}]] {{#if:{{{14|}}}|─ {{{14}}} }}</li><br />
}}{{#if:{{{15|}}}|<li>[[toj:{{{15|}}}|{{{15|}}}]] {{#if:{{{16|}}}|─ {{{16}}} }}</li><br />
}}{{#if:{{{17|}}}|<li>[[toj:{{{17|}}}|{{{17|}}}]] {{#if:{{{18|}}}|─ {{{18}}} }}</li><br />
}}{{#if:{{{19|}}}|<li>[[toj:{{{19|}}}|{{{19|}}}]] {{#if:{{{20|}}}|─ {{{20}}} }}</li><br />
}}</ul><br />
}}</div>
Xiplus