競技プログラミングの作問環境構築(gitとrime編)

この記事はCompetitive Programming (1) Advent Calendar 2020 - Adventar5日目の記事です。
前日はりあんさんで「yukicoderでtestlib を使うためのメモ」でした。この記事の内容とも関連があるのでぜひ読んでみてください。


前回のSlackとの連携編からの続きです。今回の目的は、rimeを用いてテストケース作成・想定解のチェックが出来るようになること、またgitによる基本的なバージョン管理も行えるようになることです。

構成予定

  1. wiki設置(リンク
  2. Slackとの連携(リンク
  3. gitとrimeの使い方(今回)
  4. GitHub Actionsでの自動テスト
  5. コンテスト開催の準備(主に問題文)
  6. コンテスト開催の準備(その他)
  7. コンテスト本番

競技プログラミングにおいて、テストケースを作ったり想定解のテストをしたりを自分でやるのは(難しくはないにしても)大変です。そこで、JAGという団体の方が作っているrimeというツールを利用することにします。rimeの使い方は、基本的にこのブログなので適宜beetさんのブログも参照してください。rimeの公式ドキュメントにも情報があります。

まず、今後の準備としてgitを使える用にしておいてください。既にgitは使えるようになってるよ、っていう人も最新版にアップデートしておいてください。割と最近脆弱性が公開されています*1。後々GitHubを使うことになるので、Windowsの人はGitHub Desktopを導入しておくと色々楽かもしれません。最新版のGitHub Desktopではさっきの脆弱性は修正されているらしいです。今回の作業に際してGitHubのアカウントは無くてもいいんですが、どうせ後で必要になるのでまだ持っていない人は作っておくと良いです。また、rimeを動かすためにはPython3が必要なので使える用にしておいてください。gitとPython3の導入が難しい・うまくいかないという人は、身の回りの詳しい人に聞いてみてください。

さて、まずはrimeを使える用にしましょう。rimeはpipというPython用のパッケージ管理システムから入手できます。コマンドラインコマンドプロンプトPowerShellのこと)から

pip install git+https://github.com/icpc-jag/rime

とか打つと使える用になります。一部環境では

pip3 install git+https://github.com/icpc-jag/rime

とか打つ必要があるかもしれません。また、gitを生まれて初めて使う場合にはユーザー名の登録が必要かもしれませんので

git config --global user.name "ユーザー名"
git config --global user.email "メールアドレス"

とかやってください。GitHubアカウントと同じメアドを入れておきましょう。また、pipが古い場合には、

pip install --upgrade

とかを先にやってからもう一度試すとうまくいくと思います。上手くいってれば、コマンドラインでrimeと打つとマニュアルっぽいものが表示されるでしょう。ちなみに、私の環境ではgitが壊れていてうまくいきませんでした(完)。

pip install git+git://github.com/icpc-jag/rime

と打ったらうまくいったので、なんか上手くいかない人は試してみましょう。最悪の場合、gitとPython3がちゃんと動いていればなんとかなります。pipが壊れていたら無視して先に行きましょう。
立ち塞がるトラブルを克服してなんとかrimeが使えるようになったでしょうか?できた人は次のステップへ進みます。Linuxなら

cd ~

Windowsなら(ユーザー名が日本語の場合、入力するときにAlt+半/全を押して日本語入力に切り替えができるようです)

cd C:\Users\"ユーザー名"

をしてから

mkdir git

としてください。ディレクトリ名が気に入らない人は好きな名前を付けてください。以後、ここで作成したディレクトリが存在するものとして話を進めます。

cd git

をしてから、

git clone https://github.com/icpc-jag/rime.git

をしてください。全部終わったら、

cd rime

です。今移動した先のデレクトリには色々とファイルがあるのですが、まずはサンプルを確認してみましょう。先に断っておきますが、最新版のrimeでプロジェクトを作成するとexampleと少し違うものが作成されたりしますが、

cd example

をするとサンプルとして用意されたディレクトリに移動します。中身はこんな感じです。
a+b PROJECT rime rime.py
rimeの本体は「rime」ディレクトリと「rime.py」ファイルです。「PROJECT」ファイルには大したことが書いてありません。大事なのが「a+b」というディレクトリです。これは問題に関する情報(解法やテストケース)を含んだファイルです。テストする前にa+bディレクトリの中身を説明します。

cd a+b

として移動すると「PROBLEM」というファイルと「tests」というディレクトリと「cpp-correct」などの「言語名-色々」という形式のディレクトリがたくさんあります。まずは「PROBLEM」ファイルを見てみます。

ここでは問題のタイトルや実行時間の制限など問題に関する基本的な設定ができます。

reference_solution="cpp-correct",

のようにすると想定解を指定することもできます。必要に応じて変更してください。
次にtesterの書いたコードの扱いについて見ていきます。「言語名-色々」という形式のディレクトリ1つが1つのtester解に相当します。

cd cpp-correct

として「cpp-correct」のディレクトリに移動すると「SOLUTION」というファイルがあります。

このファイルはtester解がどの言語で書かれているのかを指定するものです。必要に応じて1つを指定してください。どの言語が対応しているのかはよく分からないのですが割と幅広く使えるようです。

cxx_solution(src='main.cc', challenge_cases=[])

のようにすると想定誤解法も扱えます。このように指定した解法が正解してしまうとエラーとなります。失敗するケースが決まっている場合にはケース名を指定することもできます。
次にテストケースの生成について見ていきます。

cd ../tests

とすると「TESTSET」というファイルがあります。

このファイルはテストケースを生成、検証する言語を指定するものです。出力検証器が必要な場合もここで指定します(ちなみに今回は出力検証の説明はしません)。入力生成用のコードではテストケースをファイルに書き出し、入力検証用のコードでは標準入力からテストケースを読み込むようにします。ミスを防ぐために制約をまとめた独立したファイルを作成しそれぞれのコードから読み込むようにすると良いです。
さて、このようにしてテストケースと想定解が用意できたらそれらが上手く動くかテストをします。想定解以外にACできるかテストしたいコードがあれば疑似的なジャッジシステムのようなことができます。

cd ../..

として「a+b」の問題ディレクトリがあるところまで移動してから

./rime.py test a+b

とするとテストが始まります。テストケースの生成に失敗した時や入力検証器がエラーとなった時や想定誤解法以外が想定解と異なった時など、問題がある時はエラーメッセージが流れます。
では、実際に新規にプロジェクトを作成していきます。先ほど作成した「git」というディレクトリに移動し、新たにお試しのプロジェクトを作成します。

mkdir otameshi
cd otameshi
rime_init --git

のようにすると自動でgitの初期化とPROBLEMファイルの作成が行われます。ここで

rime add . problem first_problem

とすると何か開くかもしれません。今はとりあえず何も変更せず保存します。すると「first_problem」というディレクトリができるので

cd first_problem

として問題ディレクトリに移動します。

rime add . solution test-ac

とすると解法のディレクトリを追加することができます。先ほど説明した「SOLUTION」だけができるので自分の作った想定解を同じディレクトリに追加すれば良いです。今回は想定解が無いので適当な言語の行のコメントアウトを外して保存します。
同様に

rime add . testset tests

とするとテストケース作成用のディレクトリと「SOLUTION」ファイルができるのでgeneratorとvalidatorそれぞれ適当な言語の行をコメントアウトして保存します。このようにしたら別解や想定誤解法を追加していけば良いです。

最後にgitを用いた作業状況の管理について少し説明します。rimeはプロジェクトの初期化時にgitignoreなどを自動で設定してくれるのでgitで管理すると便利です。新しく解法などを追加したときなど作業に区切りが付いた時などにcommitすると良いです(そのタイミングでテストをしたりします)。詳しい手順に関しては様々な流儀があるためここでは解説を省きます。個人的にオススメのサイトはこちらです。分からないことなどあればこちらまでお願いします。

次回は「GitHub Actionsでの自動テスト」です。