11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AHC初心者向け、ローカルテスタの使い方

Last updated at Posted at 2025-01-19

はじめに

AHCを始めたばかりの方の「そもそもローカルテスタの使い方がわからない」という声をよくみかけます。
AtCoderユーザは一般的なプログラマー層と比べ、コマンドプロンプトの使い方がわからないという方が多い印象なので、そのあたりを解説する記事が必要かなと思います。
具体的にはあぷりしあさんの記事でAHC040のコマンドの使い方を解説していますが、もう少し汎化し、今後の新しいAHCでも自力でコマンドを打てるようになってもらうことを目指します。
1回だけテスターを実行するならもっと楽な方法(ビルド済みテスタ)があると思いますが、今回は継続的にAHCをやるためにちゃんと環境構築から紹介します。

WSL(Windows Subsystem for Linux)をインストールする

前書き

Windowsユーザ以外は無視してください。
WSLはWindows上でLinuxを動かすことができるものです。
一部のAHCのローカルテスタのReadmeにはPowerShellへの言及もありますが、どうせなんやかんやLinuxを使いたくなる時がいずれ来ますし、多くのエンジニア向けの記事はLinuxを前提としています。
この機会にLinux上で開発することを覚えちゃいましょう。
なお、ここではLinuxの中でも特にUbuntuというものを前提とします。
Ubuntu以外のLinuxを使っている人は十分にコマンドの理解がある人が多いと思いますので、本記事の対象外とします。

インストール

基本的には公式ドキュメントに従えばいいのですが、
PowerShell または Windows コマンド プロンプトを管理者モードで開き、wsl --install コマンドを入力し、マシンを再起動します。
なお、コマンドプロンプトを管理者モードで開くには、[Windowsキー] + [R]を押した後にcmdと入力し、[Ctrl] + [Shift] + [Enter]を押せばいいです。

wsl --install

古いPCの場合はBIOSの設定を変更する必要があるかもしれませんが、最近のPCであれば概ね上記のコマンドで大丈夫だと思います。

Rust環境のインストール

前書き

Windows用にビルドされたローカルテスタのバイナリが提供されていますが、Readmeの書き方が「cargo runの部分を●●に置き換えてください」のような書き方をされがちで、そこが混乱のもとになっているようです。
最初はめんどうかもですが、Rustの環境を先に整えておいたほうが、今後のAHCでReadmeの書き方が変わっても対応しやすいと思います。

インストール

これも基本的には公式ドキュメントに従えばいいのですが、ドキュメントに当たり前のように書いてあるcurlコマンドは、デフォルトのLinux環境では存在しません。

そこで、以下のようなコマンドを打ってcurlをインストールします。

sudo apt update
sudo apt install curl

まず、sudoというコマンドは、そのコマンドを実行するユーザの権限を上げるコマンドです。 1
hogeというコマンドを実行するときにsudo コマンド名とすると、管理者権限でコマンド名を実行できます。
aptというコマンドは、パッケージ管理用のコマンドで、引数によって異なる挙動をします。
apt updateでパッケージのインデックスファイルを更新します。
apt install パッケージ名でそのパッケージをインストールします。
apt updateをしないとそのパッケージの最新版があっても古いバージョンがインストールされる可能性があるため、基本的にはapt updateapt install パッケージ名はセットで実行します。
これらはシステムに変更を加えるコマンドのため、管理者権限がないと実行できません。

curlのインストールの流れをまとめると、以下のような流れです。

  1. sudo apt updateでパッケージのインデックスファイルを更新する(管理者権限でないと実行できないため、sudoをつけている)
  2. sudo apt install curlcurlをインストールする(管理者権限でないと実行できないため、sudoをつけている)
コマンド 説明
sudo 引数に与えたコマンドを管理者権限で実行する
apt パッケージ管理用のコマンド
updateでパッケージのインデックスファイルを更新する
install パッケージ名パッケージ名をインストールする

続いて、以下のコマンドでRustをインストールします。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

curlはデータを取得するコマンドで、下表に記したように、各種オプションで指定した形で、指定したURLからデータを取得します。
|はパイプというもので、左辺のコマンドの出力を右辺のコマンドの入力として扱います。
shはシェルスクリプトを実行するコマンドで、この場合の意味としては標準入力をシェルスクリプトとして実行します。

Rustのインストールの流れをまとめると、以下のような流れです。

  1. curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rsでRustのインストーラーをシェルスクリプトとして取得する
  2. |で後続のコマンドの入力として1のシェルスクリプトを渡す
  3. shでシェルスクリプトを実行する

なお、ここでインストールしたrustupはRustのツールチェーンで、コンパイラであるrustcやビルドシステム兼パッケージマネージャであるcargoといったRustの重要な一連のツールが入っています。

コマンド 説明
curl データを取得するコマンド
--proto '=https'でHTTPSプロトコルを使用する
--tlsv1.2で暗号化し、安全に通信する
-sで進捗を表示しない
-S-sと併用すると、エラーメッセージだけ表示する
-fで異常検知
https://sh.rustup.rsでRustのインストーラーのURLを指定する
sh シェルスクリプトを実行するコマンド

ローカルテスタのコマンドとその意味

ローカルテスタの配置

さて、ようやく本題です。
まず、問題文の中の以下のようなリ記述の中からローカル版のリンクをクリックし、zipファイルをダウンロードします。回によっては、ローカルテスタなど微妙に異なる言い回しなので注意してください。

question_html.png

ダウンロードしたzipファイルを展開し、toolsに移動します。
toolsディレクトリの場所は人によりますが、以下は一例です。
なお、WSLを使う際に/mnt以下のディレクトリにアクセスすると処理が遅くなりますが、今回は無視することにします。

cd /mnt/c/Users/ユーザ名/Downloads/ahc002/tools
コマンド 説明
cd 指定したディレクトリに移動するコマンド

toolsディレクトリは、だいたい以下のような構成になっています。

tools
├── Cargo.lock
├── Cargo.toml
├── README.html
├── README.md
├── in
│   ├── 0001.txt
│   ├── ...
│   └─── 0099.txt
├── seeds.txt
└── src
    ├── bin
    │   ├── gen.rs
    │   ├── tester.rs ない場合もある
    │   └── vis.rs
    └── lib.rs

ここで、多くのAHCでは以下の3つ以内のコマンドの使い方がREADMEに記載されています。

  1. cargo run -r --bin gen seeds.txt
    seed.txtに記載された乱数seed値を用いて入力ファイルを生成する
  2. cargo run -r --bin tester cmd < in.txt > out.txt
    指定された入力ファイルを用いてコマンドを実行し、その結果をout.txtに出力する
  3. cargo run -r --bin vis in.txt out.txt
    指定された入力ファイルと出力ファイルを用いて、過程を可視化する

3つに共通するのは、cargo run -r --bin コマンド名です。
これは、先ほどcargoによってsrc/bin/コマンド名.rsをビルドし、バイナリを実行するコマンドです。

コマンド 説明
cargo Rustのビルドシステム
runで実行可能ファイルのビルドと実行をする
-r--releaseの省略形で、デバッグ情報を含まないバイナリをビルドする
--binsrc/bin/コマンド名.rsを対象にする。(Cargo.tomlに記載があればそこも対象になる)

ここで、genは入力ファイルを生成する目的ですが、zipファイルに入力ファイルが100ケースほど付属しているため、実行しなくてもAHCの参加は可能です。
また、visはビジュアライザですが、web版のビジュアライザが優秀なため、これもやはり実行しなくてもAHCの参加は可能です。
よって、参加に必須なのはtesterのみです。

テスト方法(testerがない場合)

testerは提供されるコンテストと提供されないコンテストがあります。
多くの場合、AtCoderの問題は参加者のプログラムが標準入力で入力を1回だけ受け取り、標準出力で1回だけ答えを出す仕組みをとっています。
これは、参加者が作成したプログラムだけで処理が完結するため、特に外部のテスタを用いる必要がないためです。
この場合、toolsディレクトリ内で以下のようなコマンドでテストを行います。
コマンド < 入力ファイルは、入力リダイレクトというもので、入力ファイルの内容をコマンドに標準入力として渡します。
コマンド > 出力ファイルは、出力リダイレクトというもので、コマンドの標準出力を出力ファイルに書き込みます。

mkdir -p out
あなたのプログラム実行コマンド < in/0000.txt > out/0000.txt
コマンド 説明
mkdir 指定したディレクトリを作成する
-pは複数階層の作成。既に存在する場合にエラーを出さない目的でも使える。

あなたのプログラム実行コマンドは、どの言語を使っているかによって異なりますが、一般的にはコンパイル言語とインタプリタ言語に分かれると思います。(Javaみたいに中間コードを作成する言語は別の名称な気がしますが、その辺使ってる人は雰囲気でわかってくれるでしょう)

コンパイル言語であるc++を使い、tools直下にmain.cppを配置した場合は以下のように一度コンパイルをした後に実行します。

mkdir -p out
g++ -std=gnu++20 -O2 -o a.out main.cpp # コンパイル(言語によって異なる)
./a.out < in/0000.txt > out/0000.txt # 実行(tools直下にa.outをビルドしたと仮定)

インタプリタ言語であるpythonを使い、tools直下にmain.pyを配置した場合は以下のように実行します。

mkdir -p out
python main.py < in/0000.txt > out/0000.txt # 実行(tools直下にmain.pyを配置したと仮定)

テスト方法(testerがある場合)

一部のコンテストでは、参加者のプログラムがが標準入力で入力を受け取り、標準出力に出力したらまた入力を受け取り、出力し、…と繰り返すタイプのものがあります。
このようなコンテストはインタラクティブと呼ばれ、参加者のプログラムだけでは完結しません。
そのため、testerというツールを用いてテストを行います。2
何も知らない状態で見ると複雑に見えるかもしれませんが、testerがない場合を学んだので、ほとんど同じコマンドだということがわかりますね。

mkdir -p out
cargo run -r --bin tester あなたのプログラム実行コマンド < in/0000.txt > out/0000.txt

あとはあなたのプログラム実行コマンドの部分を置き換えるだけです。

コンパイル言語の例

mkdir -p out
g++ -std=gnu++20 -O2 -o a.out main.cpp # コンパイル(言語によって異なる)
cargo run -r --bin tester ./a.out < in/0000.txt > out/0000.txt # 実行(tools直下にa.outをビルドしたと仮定)

インタプリタ言語の例

mkdir -p out
cargo run -r --bin tester python main.py < in/0000.txt > out/0000.txt # 実行(tools直下にmain.pyを配置したと仮定)

今後のAHCにむけて

今までの傾向から、testerの有無だけ気を付けておけば最低限のテストができそうなことがわかりました。
しかし、今後のAHCで、gen,tester,visの3つ以外のコマンドができる可能性や、これらのコマンドの仕様が変わる可能性があります。後述のAppendixにも記載しますが、過去にgenの仕様が変わったことがあります。
そのため、リダイレクト<,>やパイプ|の意味をしっかり理解し、READMEを自力で読み解けるようにはなっておきましょう。

Appendix: 今までのローカルテスタのREADMEのコマンドのまとめ

今回の記事を書くにあたり、過去のREADMEを全て確認しました。
ahc001はまだ運営側もどう説明するか探っている印象があります。
<input_file>はファイル名を自由に変えていいという意図があるんでしょうが、リダイレクトと勘違いしそうなので、ahc002以降ではin.txtとして統一しているようです。
cargo runのオプションも、-r--releaseで表記揺れがありますが、同じ意味だと知っていれば怖くないですね。
ahc001のgenのみ、seeds.txtの指定方法が引数ではななく入力リダイレクトになっています。これは明確に異なるものなので、過去問を復習する際に自作ツールで自動化している人は注意しましょう。

contest gen tester vis
ahc001 cargo run --release --bin gen < seeds.txt cargo run --release --bin vis <input_file> <output_file>
ahc002 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc003 cargo run --release --bin gen seeds.txt cargo run --release --bin tester in.txt cmd > out.txt cargo run --release --bin vis in.txt out.txt
ahc004 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc005 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc006 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc007 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc008 cargo run --release --bin gen seeds.txt cargo run --release --bin tester cmd < in.txt > out.txt cargo run --release --bin vis in.txt out.txt
ahc009 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc010 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc011 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc012 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc013 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc014 cargo run --release --bin gen seeds.txt' cargo run --release --bin vis in.txt out.txt
ahc015 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc016 cargo run --release --bin gen seeds.txt cargo run --release --bin tester cmd < in.txt > out.txt
ahc017 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc018 cargo run --release --bin gen seeds.txt cargo run --release --bin tester cmd < in.txt > out.txt cargo run --release --bin vis in.txt out.txt
ahc019 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc020 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc021 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc022 cargo run --release --bin gen seeds.txt cargo run --release --bin tester cmd < in.txt > out.txt cargo run --release --bin vis in.txt out.txt
ahc023 cargo run --release --bin gen seeds.txt cargo run --release --bin vis in.txt out.txt
ahc024 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc025 cargo run -r --bin gen seeds.txt cargo run -r --bin tester cmd < in.txt > out.txt cargo run -r --bin vis in.txt out.txt
ahc026 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc027 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc028 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc029 cargo run -r --bin gen seeds.txt cargo run -r --bin tester cmd < in.txt > out.txt cargo run -r --bin vis in.txt out.txt
ahc030 cargo run -r --bin gen seeds.txt cargo run -r --bin tester cmd < in.txt > out.txt cargo run -r --bin vis in.txt out.txt
ahc031 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc032 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc033 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc034 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc035 cargo run -r --bin gen seeds.txt cargo run -r --bin tester cmd < in.txt > out.txt cargo run -r --bin vis in.txt out.txt
ahc036 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc037 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc038 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc039 cargo run -r --bin gen seeds.txt cargo run -r --bin vis in.txt out.txt
ahc040 cargo run -r --bin gen seeds.txt cargo run -r --bin tester cmd < in.txt > out.txt cargo run -r --bin vis in.txt out.txt
  1. 多くの記事ではこのようなコマンドの説明までしないと思いますが、本記事はLinuxコマンドを知らない人を対象としているので、細かく説明します。わかる人にはかなり冗長になるかもしれませんが、ご了承ください。

  2. AHC015のように、入力が工夫されていてtester無しで実行できるインタラクティブ問題もあります。

11
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?