あなたが知らないかもしれない、そして知ると多分得する、online-judge-toolsの4つの機能(+2)
(この記事の和訳です。)
競技プログラマ向け。
あなたはonline-judge-toolsを知っていますか?
もし使ったことがないなら試す価値があるツールでしょう。
競技プログラミング中の操作を自動化でき、競技プログラミングエクスペリエンスは快適なものになります。
online-judge-tool
は一見すると単純に見えます。主にログイン、ダウンロード、テスト、提出のわずか4つのサブコマンドから構成されます。
しかし、oj test --help
を叩いてみると、実に20ものコマンドラインオプションがoj test
に存在していることがわかります。
そればかりか、ほかのサブコマンド(login
, download
and etc.) も同様に多くのコマンドラインオプションを持っています。
メンテナの私も「こんなのあったっけ?」となっているくらいです。
そこで今回は、私が一押しする機能を紹介したいと思います。
1. Side-by-Side diff
これはかなり新しいoj test
の機能なので、知らない方も多いでしょう。
oj test
の結果はプレーンテキストとして出力され、ユーザーが出力と期待値の差分を探す必要がありますが、
これは少々面倒な作業です。例を出します。
$ oj test -c './a.out' [*] 1 cases found [*] sample-1 [x] time: 0.054696 sec [-] WA output: 7 1 5 1 3 7 7 89 9 2 2 6 5 2 4 6 1 8 5 9 10 0 29 56 expected: 7 1 5 1 3 7 7 89 9 2 2 6 5 2 4 6 1 3 5 9 10 0 29 56
outputとexpectedの違いを見つけられたでしょうか?
ここでside-by-side表示オプション(-S
)を有効にしてみます。すると、
これぞ、visualizationの力というやつです。
期待値の"3"になるはずのところが、出力では"8"になっていることがすぐわかったでしょう。
2. MLEとTLEチェック
競技プログラミングのほとんど全ての問題が計算時間(TLE)とメモリ使用量(MLE)の制限を課しているので、 期待値と出力の一致だけでなくこの制約をプログラムが満たしていることを確認したいと考えるのは自然です。
ojでは --tle
および--mle
オプションを加えるだけで制約の確認をすることが出来ます。
例えばプログラムが2.5sec以内に終わるか確認したいときは、下記のように実行できます。
$ oj t -c './a.out' --tle 2.5 # 2.5sec [*] 1 cases found [*] sample-1 [x] time: 2.503372 sec [-] TLE
同様に、MLEも確認できます。ここで、単位はMBです。
$ oj t -c './a.out' --mle 56 # 56MB
注記: このオプションはgnu timeを必要とするため、Windowsでは未サポートです。
3. 浮動小数点誤差ジャッジ
いくつかの問題は浮動小数点型での出力を要求します。(例. 2.500000) 多くの場合、このような問題では一定の大きさの相対および絶対誤差が許容されます。
oj test
はこのような誤差ジャッジを-e
オプションを指定することによって実行することができます。
もし、何も指定せずに期待値が3
の問題に対してあなたのプログラムが3.00000001
を出力した場合、以下のように結果はWAとなります。
$ oj t -c 'echo 3.00000001' [*] 1 cases found [*] sample-1 [x] time: 0.004793 sec [-] WA output: 3.00000001 expected: 3
しかし、-e
を指定してやることで結果は変わります。
$ oj t -c 'echo 3.00000001' -e 0.000001 [*] 1 cases found [*] sample-1 [x] time: 0.004088 sec [+] AC
このように、ACになります。
ここで、oj t -c 'echo 3.00000001' -e 0.000001
の代わりにoj t -c 'echo 3.00000001' -e 1e-5
と指定しても同じ結果が得られます。
後者の方が便利な場合も多いでしょう。
4. API
ツール開発者向けの機能です。
Pythonスクリプトからonline-judge-tools
をimportすることによって、内部の関数の力を使い、
あなたオリジナルの強力なコンテストヘルパーを組むことができるでしょう。
例えば私はAPIを使って、次の問題にジャンプする機能を自作のIDEに追加しています。
ここでは問題のURLから次の問題のURLを得るスニペットを書いておきます。
from onlinejudge import dispatch from onlinejudge._implementation.utils import ( default_cookie_path, with_cookiejar, new_session_with_our_user_agent, ) def get_next_problem(cur_problem_url: str) -> str: cur_problem = dispatch.problem_from_url(cur_problem_url) contest = cur_problem.get_contest() with with_cookiejar(new_session_with_our_user_agent(), path=default_cookie_path) as sess: problems = contest.list_problems(session=sess) for i, problem in enumerate(problems): if problem == cur_problem: next = problems[(i + 1) % len(problems)].get_url() return next next_url = get_next_problem("https://codeforces.com/contest/1312/problem/B") print(next_url)
そんなに難しくない感じですね。 もしCodeforcesにログイン済ならこのスクリプトを実行すると"https://codeforces.com/contest/1312/problem/C"という文字列が出力します。.
ぜひ、まだ見ぬ素晴らしい機能を開発してみてください。
追記:日本の読者の為にもう二つ追加することにしました
5 Windows版実行バイナリ
Windowsからの使用は、WSLから使うことを推奨していますが、生のWindowsでも使える実行バイナリを配布しています。
Release v9.0.0 · kmyk/online-judge-tools · GitHubここから、oj.exeをダウンロードし、oj.exeがあるディレクトリで、oj.exe login https://codeforces.com/
を実行してみてください。
6 秘技・wait時間削り
これは少々危険なテクニックですが、oj submit
をより高速に終了し、提出時間を縮めることができます。
あまりパフォーマンスが上がるとは思えませんが、First Answer狙いなら試す価値があります。
oj submit
に-w 0.1
などと指定してやることで、実際に提出するまでのwait時間が0.1秒にできます。0秒にも出来ます。デフォルト3秒なので、3秒提出が早くなります。
ただし、このwait時間はいたずらに設けてあるわけではありません。
コマンドをミスして発行してしまった時に、Ctrl+Cでキャンセルする時間が与えられているということです。 wait時間を削減すれば最大3秒縮まりますが、ミスしてsubmitしたらペナルティ5分を失います。
通常これはリスクに見合わない選択肢であり、作者(kmyk先生)は推奨しておりません。私は「男は度胸!」と信じております。現場からは以上です。