Python と VSCode で競プロ - 標準入力の簡易化とサンプルケース判定の自動化 -

【2022-10】見出しを修正しました。

最近 AtCoder で競プロを始めました :beginner:
始めたのはいいのですが、パッとは解けないので何度も何度もデバッグ地獄です :sob:
そのたびターミナルにテストケースをコピペの嵐...
もうそんなことはやめよう :no_entry_sign:

この記事は
windows10 1909
VSCode 1.45.1
Python 3.8.2
で確認した内容となっています。

# 1. 標準入力の簡易化
まずは標準入力の簡易化です。

「VSCode  python 標準入力」などの条件で検索していると、teratail にこんな質問と回答がありました
[VS Codeで標準入力を受け取る方法(Windows10・Python)](https://teratail.com/questions/251619)
競プロ界隈では有名なのかわかりませんが、私が探していたのはまさにこれでした。

```python
import io
import sys

_INPUT = """\
2
1 2 3
aaa
"""
sys.stdin = io.StringIO(_INPUT)

print(int(input()))
print(list(map(int, input().split())))
print(list(input()))

# 出力
2
[1, 2, 3]
['a', 'a', 'a']
```

Python ドキュメントによると [sys.stdin](https://docs.python.org/ja/3/library/sys.html#sys.stdin) は (`input()` の呼び出しも含む) すべての対話型入力に使われるもので、[io.StringIO](https://docs.python.org/ja/3/library/io.html#io.StringIO) は、要するにファイルのように文字列を読み書きするクラスのようです。

<details><summary>テンプレート</summary><div>

```python:test_inut.py
import io
import sys

# input here
_INPUT = """\

"""
sys.stdin = io.StringIO(_INPUT)

# your code here

```
</div>サンプルケースや自分で考えたテストケースとデバッグしたいコードを入れてください。</details>
なにより別ファイル（ input.txt など）に書いておくのと違い、テストケースがパッと見えるのもいいですよね。
これでコピペの嵐に悩まされることはなくなりました :clap:

# 2. サンプルケース判定の自動化
サンプルケースの判定を自動化するツールがあります！！それは
[online-judge-tools](https://github.com/online-judge-tools/oj)
です。

online-judge-tools はコンテストサイトからサンプルケースをスクレイピングし、判定を自動化してくれるありがたいツールです。

> OS には Linux か Mac OS を推奨しますが、 Windows 上でも動作します。

と書かれている通り、私の環境では何の問題もなく動作しています。

## 使い方
使い方に関しては、[GitHub](https://github.com/online-judge-tools/oj) ページの他、
[Visual Studio Codeで競プロ環境構築(実践編)](https://qiita.com/AokabiC/items/af685bfd205dda44ec45)
[AtCoderで自動サンプルテストケース&手入力値テスト実行 with VS Code](https://qiita.com/chokoryu/items/4b31ffb89dbc8cb86971)
を参考にさせていただきました。

### フォルダ構成

```
AtCoder\
├── .venv\
│
├── .vscode\
│   └── tasks.json
│
├── sctipt\
│   └── cptest.ps1
│
├── src\
│   └── abc000_0.py
│
└── test\
    └── abc000_0\
        ├── sample-1.in
        └── sample-1.out
```
.venv フォルダは仮想環境を構築した際の名前と読み替えてください。なくても構いません。.vscode フォルダは tasks.json を生成した際自動的に作成されます。script フォルダと src フォルダは絶対必要というわけではありません。test フォルダは cptest.ps1を実行した際に自動的に作成されます。
### 1. インストール
```shell
> pip install online-judge-tools
```
pip で簡単にインストールできます。

### 2. ログイン
ユーザー名とパスワードを入力します。

```shell
> oj login -u ユーザー名 -p パスワード "https://atcoder.jp/"
```
ログインできたか確認するには

```shell
> oj login --check "https://atcoder.jp/"
```

```
[*] You have already signed in.
```
と返ってくれば OK です。

### 3. cptest.ps1
コンテストサイトからサンプルケースを取得し、テストするスクリプトです。

以下は参考にさせていただいたスクリプトを`.ps1`にし、変更を加えたものです。

```powershell:cptest.ps1
. ".venv/Scripts/Activate.ps1"

$problem_name = $Args[0]
$problem_name_list = ($problem_name -split "_")
$base_url = ($problem_name.Replace("_", "-")).Substring(0, ($problem_name.Length) - 2)

if (! (Test-Path $test_dir)) {
    oj dl -d test/$problem_name/ https://atcoder.jp/contests/$base_url/tasks/$problem_name
}

oj test -c "python src/$problem_name.py" -d test/$problem_name/
```

私は AtCoder フォルダ内の仮想環境に online-judge-tools をインストールしたため、1行目で`.venv/Scripts/Activate.ps1`を読み込み、仮想環境を activate しています。仮想環境でない方は必要ありません。

また、[第二回全国統一プログラミング王決定戦予選 A - Sum of Two Integers](https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_a) などのURLは
https\://atcoder.jp/contests/**nikkei2019-2-qual**/tasks/**nikkei2019_2_qual_a**
`$base_url`にハイフン、`$problem_name`にアンダーバーが使われているため、`_`を`-`に変える処理を追加しています。（変更しました。）

### 4. tasks.json
VSCode の**タスク**は、様々な作業を自動化する機能で、`Ctrl+Shift+B`で実行することができます。
そこで、`cptest.ps1`を実行できるようにしましょう。

`Ctrl+Shift+P`でコマンドパレットを開き、`task`と入力すると、多くのコマンドが表示されます。その中から、「タスクの構成」→「テンプレートから tasks.json を生成」→「 Others 」と選んでいくと、tasks.json が生成されます。

```json-doc:tasks.json
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "test_atcorder_sample",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "type": "shell",
            "command": "${workspaceFolder}/script/cptest.ps1",
            "args": [
                "${fileBasenameNoExtension}"
            ]
        }
    ]
}
```
これで、ファイル名が`abc060_b.py`ならば`Ctrl+Shift+B`で

```shell
> cptest.ps1 abc060_b
```
を実行したことになります。

使い方は以上です。このツールはほかにも、提出やストレステストも行えるそうです。サンプルケースのテストを自動化できるだけでもありがたいのにどれだけですか :joy:
私はまだまだ使いこなせていないのでこれから頑張ります。

# さいごに
本当にデバッグが楽になりました。この記事がほかの競プロ初心者を少しでも助けることができれば幸いです。
みなさま良き競プロライフを :wave: