verilog書く人

自称ASIC設計者です。どなたかkaggle一緒に出ましょう。

あなたが知らないかもしれない、そして知ると多分得する、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)を有効にしてみます。すると、

f:id:segafreder:20200318224656p:plain

これぞ、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先生)は推奨しておりません。私は「男は度胸!」と信じております。現場からは以上です。