feature image

2025年12月6日 | ブログ記事

ICPCライブラリを自作してみた話

この記事は アドベントカレンダー2025 6日目の記事です。

はじめに

24Bの @zoi_dayo です。普段はたまに競プロをしたりしています。

少し前にICPC Taichung Regionalに出てきました。このときにチームのライブラリを作ってみたので紹介します。

ICPC Taichung Regional 2025 参加記 (zoi_dayo視点)
この記事はアドベントカレンダー2025 4日目の記事です。 はじめに 24Bの @zoi_dayo です。普段はゲームを作ったり絵を描いたりたまに競プロをしたりしています。 11/15,16に開催された ICPC Taichung Regional に参加してきたので記事を書きます。 ICPC Regional ってなに この記事を開く方なら知っているかもしれませんが、一応。 ICPCは大学対抗国際プログラミングコンテストです(略)。いろいろ細かいルールがあるのですが、基本的に大学内で3人チームを組み、 地区予選 (日本予選) → Regional (日本大会) → Playoff (アジア太平洋大会) → World Final と進んでいくことになります。 東京科学大学は東大・京大に続く競技プログラミング強豪校であり、競技プログラミングのプレイヤーの層が非常に厚いです。しかもtraPが取りまとめるおかげでICPCへ参加するハードルが下がっており、地区予選には25チーム前後が出場します。 ここから日本上位n位までが勝ち抜ける...というルールであればよいのですが

ところで明日にICPC Yokohama Regionalがあるらしいです。応援!!

ライブラリって何

競プロではいろいろ典型的なテクニックが要求されます。特にデータ構造などであれば、一度汎用的なコードを作れば、次からはそれを使い回すだけでよいことが多いです。これをいちいち書いていると大変なのでコード片をメモしておこうということです。

AtCoderに参加している人なら、 ac-library をご存知かもしれません。AtCoderのC++環境でデフォルトで使用可能になっているAtCoder公式ライブラリです。

他にも Nyaan's LibraryLuzhiled's Library なども有名なんじゃないかと思います。これらは verification-helper あたりのツールを利用して作られていることが多いですね。

ところが、ICPC用のライブラリとなるとすこし要件が変わってきます。ICPCでは、(大会によりルールが異なるので一概には言えませんが) 「A4片面 25ページ以下の紙ライブラリのみ持ち込み可能」のようなルールが定められていることが多いです。すなわち、通常のコンテスト用ライブラリとは異なり、

などが求められます。

ので、ICPCに出場するチームは、多くの場合は Speed Star の ICPC NotebookKACTL を利用します。というかぶっちゃけこれらが最強です。あれ... (記事終了)

つくってみよう!

Speed StarのライブラリやKACTLを使ってもよいのですが、これらのライブラリには知らないデータ構造とかが大量に乗っており、またもう少し日本語のドキュメントを載せておきたいと感じたので、チームのライブラリを作ってみたいねという話になりました。

出来たものがこれです:

GitHub - ICPC-Tsukuyom1/Tsukuyom1_Library
Contribute to ICPC-Tsukuyom1/Tsukuyom1_Library development by creating an account on GitHub.

ライブラリのコードは、基本的にメンバーが持っていたもの + kactlやNyaan's Librayを参考に編集したものを集めています。ので、網羅性としては各種ライブラリの下位互換という感じです。

その分ページ数に余裕が出るので、使い方、参考情報などのドキュメントは増やしています。

こだわりポイント

ここからはこだわりポイントの紹介です。

PDF化

印刷前提のライブラリなので印刷できないといけません。この目的なら普通は ICPC Notebook を利用するとよいです。なぜ使わなかったのか? わかりません...

要件を整理します。

まず候補に上がるのが Markdown → PDF 系のツールです。Markdownは (Webの各所で使われていることから分かる通り) 簡単にHTMLに変換することが出来ます。というかHTMLをドキュメントに特化させた省略記法です。
HTMLまで変換してしまえば、あとはヘッドレスなブラウザを起動し、ブラウザの印刷機能を利用してPDFに変換することができます。ここまでをやってくれるツールはWebの各所に落ちています。

これは便利なのですが、昔使ったときに改ページのところで文字が切れてしまったような記憶があるのと、段組のレイアウトを作るためににはCSSを頑張らないといけないこと、またmdファイル内に外部のcppファイルを埋め込めるかわからないということで一旦別の方法を考えてみることにしました。(あとヘッドレスブラウザが重いのでできればCIで動かしたくない)

ここで選んだのがTypstです。レポートなどに使っている方も多いと思うのですが、簡易版TeXのような存在です。(TeXほどではないですが) 柔軟なレイアウトが可能で、md(HTML)とは異なり最初から印刷物の作成を想定したツールなので都合が良いです。

Typstには #import#include という機能があり、他のTypstファイルの内容を埋め込むことが出来ます。また、 #outline() で目次も作れるし、codelst パッケージ#sourcefile(filename) を利用すれば外部ファイルを読み込んでシンタックスハイライト付きで表示することも出来ます。最高ですね。

GitHub Actionsを利用して、mainブランチまたはPRに変更が入った時にPDFをビルドしてArtifactとして出力するようにしています。フォントは Fira Code + Noto Sans CJK JP です。

Tsukuyom1_Library/.github/workflows/build-docs.yml at main · ICPC-Tsukuyom1/Tsukuyom1_Library
Contribute to ICPC-Tsukuyom1/Tsukuyom1_Library development by creating an account on GitHub.

ただ欠点もあって、TypstよりTeXのほうが歴史があるため、適当にGitHub Copilotに任せているとTypstファイルにTeXを書いてコンパイルエラーを出してしまいます。ちゃんとやりましょう。

Verify

前述の通り、C++のファイルを分離しているので、 #include を利用してコードを書くことができます。CIでの自動テストも走らせたいですね。

こういうときは基本 verification-helper を利用するとよいです。が、ドキュメント生成機能が2種類できるのはあまりきれいじゃないと思ったこともあり、せっかくなので自分で作ってみました。
verifyフォルダ以下に //@yosupo {問題id} または //@yukicoder {問題id} から始まるファイルを配置することで自動的にテストが走ります。Libray Checkerについては 問題が公開されている ので、ここにあるコードを用いてテストケース生成とジャッジを行いました。yukicoderについては online-judge-tools を利用しています。

GitHub ActionsのMatrix機能を利用して複数の問題のテストが同時に走るようにしています。これにより、Verify対象が増えてもそれなりの時間で完了することができます。

実行時は (Library Checkerの場合は生成時もですが) ulimit -s unlimited を忘れないようにしてください。これによりスタックサイズ上限をなくすことができます。なお、DOMJudgeでも同様のスタックサイズ上限拡張が行われているため、本番だとエラーになるということはないはずです。

domjudge/judge/runguard.cc at 2ec4c8cbfeaaf49791d3b890c04f776ad534c2d2 · DOMjudge/domjudge
DOMjudge programming contest jury system. Contribute to DOMjudge/domjudge development by creating an account on GitHub.

ドキュメント系

gdb の使い方や乱数、タイマー、bit演算 ( O(3n) のforとか) 、組み合わせの公式などドキュメントはまあまあ書いてます。ただタイマーを使う問題がICPCに出るかと言われるとかなり出ない気がしています。

作ってみて

自分たちの能力で使えて、かつ実装がめちゃくちゃ重い訳では無い、というものに関してはだいたい網羅出来たと思います。Verifyのカバレッジがかなり低いところは心配ですが... (適切な問題を見つけるのが難しい)

ライブラリ作成にTypstを利用している例はあまり見かけないのですが、かなり使いやすかったので印刷目的であればかなりおすすめです。Chromium系よりもバイナリサイズが小さいのでGitHub Actionsでの動作も軽いですし、手元での出力・プレビューも簡単です。

明日は @vPhos さん、 @jippo さんの記事が上がるそうです。楽しみ〜!!

zoi_dayo icon
この記事を書いた人
zoi_dayo

24B 競プロやWebをちょびっとやったりしていた

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2024年8月21日
【最新版 / 入門】JUCEを使ってVSTプラグインを作ろう!!!!【WebView UI】
kashiwade icon kashiwade
2023年4月27日
Vulkanのデバイスドライバを自作してみた
kegra icon kegra
2021年4月2日
DXライブラリで重力パズルゲームを作る
Macky1_2 icon Macky1_2
2023年7月13日
アルゴリズム班はやとき王選手権「競(けい)プロ」を開催しました!
abap34 icon abap34
2021年4月18日
ベズー係数とN項の拡張ユークリッドの互除法
0214sh7 icon 0214sh7
2025年9月18日
DirectX Raytracing に入門してみる
kavos icon kavos
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記