Ccmmutty logo
Commutty IT
2
10 min read

最高の環境を作ってみた Rust & AtCoder

https://cdn.magicode.io/media/notebox/1c909920-4a8b-4603-af17-e2c1f7bccc3c.jpeg

はじめに

最近知人に勧められて AtCoder を始めました。最初は Python で始めたものの、
  • 実行速度が遅い
  • 実行速度を解決しようとすると PyPy という選択肢になるが、こちらは Numpy が使えない
  • ローカルで実行する際、Python3 と PyPy で環境を使い分けるのが面倒
など、少し気になる点が多くもやもやしていました。そこで、新たに Rust を勉強しようと考えました。
この記事では、ひとまず自分なりの「快適AtCoder環境」が出来上がったので共有したいと思います。

環境

Mac でやってます。Windows は途中コマンドを変える必要があるかもしれません。

Rust をインストールする

こちらに関しては、探せばいくらでも参考資料が出てくると思いますので、そちらを参考にしていただきたいと思います。ひとまず、cargo コマンドが使用できるようになれば OK です。

VSCode をインストールする

こちらに関しても余り説明することはないです...。

拡張機能

rust-analyzer を導入します。

プロジェクトを作成する

好きな場所で AtCoder 用のフォルダを作成します。フォルダ名は自由ですが、今回は RustCoder とします。
# AtCoder 用の新規 Rust プロジェクト(RustCoder)を作成
> cargo new RustCoder
> cd RustCoder
> ls
Cargo.toml src
現在、RustCoder 内には Cargo.tomlsrc/main.rs しかないと思います。このフォルダをこれから AtCoder 用に改造しましょう。

cargo-compete をインストールする

cargo-compete に関しては、「cargo-atcoderの代替品を作った」で解説されています。簡単に説明すると、AtCoder のテストケースのダウンロードやフォルダ作成、提出などを行えるコマンドラインツールとなっています。こちらのインストールは、下記のコマンドを入力するだけで行えます。
> cargo install cargo-compete
cargo-compete がインストールできたら、先ほど作成した RustCoder 内で下記のコマンドを実行します。
> cargo compete init atcoder
Do you use crates on AtCoder?
1 No
2 Yes
3 Yes, but I submit base64-encoded programs
1..3:
cargo compete init atcoder で AtCoder 用にプロジェクトを初期化します。しかし、「AtCoder でクレートを使用しますか?」と入力を求められました。ここでは、2番を選択すると良いと思います。crate というのは、外部ライブラリとか外部パッケージのようなものです。実は Rust は標準ライブラリが少なめで、AtCoder ではあらかじめいくつかの crate がインストールされています。質問の意味は、「AtCoder で使える crate を使用しますか?」ということです。3番は「バイナリ提出」をするということを意味しています。バイナリ提出に関してはしたことがないのでよく分かりませんが、2番で問題ありません。
2番を選択すると、compete.toml, template-cargo-lock.toml, .cargo/config.toml の3つのファイルが作成されたと思います。基本的には compete.toml 以外は中身を見る必要はないと思います。

compete.toml を編集する

先ほど作成された compete.toml は、名前の通り cargo compete コマンドの設定ファイルです。このファイルの [template] と書かれた項目を探してください。おそらく、以下のようになっていると思います。
[template]
src = '''
fn main() {
    todo!();
}
'''
内容を以下のように書きかえてください。
[template]
src = '''
use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {}
}
'''
proconio は、競プロの入出力用のクレートです。これはどんな問題でも確実に使うので、[template] 内に記述して最初から使えるように設定します。

cargo-member をインストールする

これは、Cargo のワークスペースを編集するためのコマンドラインツールです。具体的にどう使用するかは後述しますが、必要となるのでインストールしておきます。
> cargo install cargo-member

コンテストフォルダを作成する

これまでの作業により、
  • Rust(Cargo)
  • VSCode(rust-analyzer)
  • cargo-compete
  • cargo-member
がインストールできたかと思います。それでは、これらを使用してコンテストのフォルダを作成していきます。
まず、VSCode で RustCoder を開きます。その後、VSCode の上部メニューからターミナルを開きます。ターミナルで以下のコマンドを実行してみてください。
> cargo compete new practice
practice contest のフォルダが作成されたと思います。このように、新しいコンテスト用のフォルダを作成するには cargo compete new コマンドを使用します。問題URLの contests の後の英数字が「コンテストID」を表しています。次に、先ほどインストールした cargo member コマンドを使用します。
> cargo member include practice
このコマンドを実行すると、practice フォルダがワークスペースのメンバーに追加されます。RustCoder/Cargo.toml を確認してみてください。
workspace = {members = ["practice"],exclude = []}
このような記述が追加されていると思います。ワークスペースのメンバーに追加をしなかった場合、VSCodeの拡張機能 rust-analyzer がうまく動作しないため注意してください。ワークスペースについて知りたい方はこちらを読んでみると良いかと思います。
また、Cargo.toml 内の上記の部分を見ると、他の部分と違う記述で浮いていてなんとなく落ち着かない人もいるかと思います。そんな繊細な方は、最初からある [dependencies] の上あたりに [workspace] と記述して保存した後に cargo member コマンドを実行すると幸せになれるかもしれません。

テストケースを試してみる

コンテストフォルダ practice を作成したので、A 問題を実際に解いていきましょう。
use proconio::{fastout, input};

#[fastout]
fn main() {
    input! {
        a: usize,
        (b, c): (usize, usize),
        s: String
    }

    println!("{} {}", a + b + c, s);
}
プログラムが書けたら、テストケースを試してみます。
> cd practice
> cargo compete test a
※エラーが発生した場合はページ下部の【追記: toolchain をインストールする(2022/5/25)】を参考にしてください。
テストを通過出来ましたか?良さそうであれば、そのまま提出してみます。
> cargo compete submit a
もしかするとログインを求められるかもしれません。その場合は、cargo compete login でログインをしてください。
このように、cargo compete を利用するとターミナル上でコンテストフォルダの作成・テストケースのダウンロード・テストから提出まで一貫して行うことが出来ます。

さらに快適な環境を求めて

コンテストフォルダを作成するたびに cargo compete new <contest>cargo member include <contest> を実行するのは面倒なので、VSCode の tasks.json を活用して自動化します。tasks.json.vscode 内に作成します。
> cd RustCoder
> mkdir .vscode
> cd .vscode
> touch tasks.json
あるいは、こちらの記事のような手順を行うことでも tasks.json を作成できます。
そして、tasks.json に以下の部分を追記します。
{
    --- 前略 ---
	"tasks": [
        --- 略 ---
		{
			"label": "rust: cargo compete new",
			"type": "cargo",
			"command": "compete",
			"args": [
				"new",
				"${input:contest}"
			]
		},
		{
			"label": "rust: cargo member include",
			"type": "cargo",
			"command": "member",
			"args": [
				"include",
				"${input:contest}"
			]
		},
		{
			"label": "new contest",
			"dependsOrder": "sequence",
			"dependsOn": [
				"rust: cargo compete new",
				"rust: cargo member include",
			],
			"presentation": {
				"echo": false,
				"reveal": "silent",
				"focus": false,
				"panel": "shared",
				"showReuseMessage": true,
				"clear": true
			},
			"problemMatcher": []
		}
	],
	"inputs": [
		{
			"id": "contest",
			"description": "contestID",
			"type": "promptString"
		}
	]
    --- 後略 ---
}
rust: cargo compete new とラベル付けされているタスクは、新規コンテストファイルを作成するタスクとなっています。このタスクの引数 args には、${input:contest} がありますが、これは一番下の inputs と関連し、入力を受け付けるようになっています。rust: cargo member include とラベル付けされているタスクは、${input:contest} で指定されたフォルダをワークスペースのメンバーに追加するタスクです。
new contest とラベル付けされたタスクは、この2つのタスクをまとめたものです。「⌘+P」→「task new contest」と入力してこのタスクを実行すると、contestID の入力を求められ、フォルダの作成とワークスペースメンバーへの追加が連続で行われます。

まとめ

自分なりに満足のいく「Rust & AtCoder」環境ができたのでまとめました。環境ばかりこだわってないでちゃんと AtCoder の勉強も頑張ろうと思います;;

追記: toolchain をインストールする(2022/5/25)

cargo compete test を実行すると、
error: toolchain '1.42.0-x86_64-apple-darwin' is not installed
のようなエラーメッセージが表示されるかもしれません。AtCoder では現在、toolchain のバージョン指定が 1.42.0 となっています。そのため、cargo-compete でテストを行う際もこのバージョンの toolchain が必要となります。以下のコマンドを実行して必要なバージョンの toolchain をインストールします。
> rustup toolchain install 1.42.0
しかし、まだ cargo compete test を実行しようとすると以下のようなエラーが表示されると思います。
--- 前略 ---
error: failed to parse manifest at `.../RustCoder/Cargo.toml`

Caused by:
  failed to parse the `edition` key

Caused by:
  supported edition values are `2015` or `2018`, but `2021` is unknown
--- 後略 ---
こちらは edition が違うというエラーです。Cargo.toml[package]edition 部分を以下のように 2018 へ変更して保存してください。
[package]
edition = "2018"
以上の作業により、cargo compete test コマンドが実行できるようになったかと思います。
ちなみに、toolchain のバージョンを変更する場合は、こちらで紹介されているような、rust-toolchain というファイルを使用する方法が一般的です。しかし、VSCode の拡張機能 rust-analyzer1.42.0 で正常に動作しません。そのため、rust-analyzer の恩恵を受けつつ cargo compete コマンドを実行するためには、rust-toolchain を使用せず、「プロジェクト全体のバージョンは最新の安定版のまま、cargo compete に必要な 1.42.0toolchain をインストールする」必要があります。

Discussion

コメントにはログインが必要です。