Rust/AtCoder cargo compete オリジナル快適設定
RustでAtCoderに参加するとき、cargo compete
を使用している人は多いと思いますが、いくつか面倒だなと思っている点を解決する快適な設定を考えてみたので、共有します。
- オリジナルテンプレート設定
- release設定
- コンテスト生成用スクリプト
- デバッグ用スクリプト
プロジェクト構成
構成は以下の通りです。
通常はないオリジナルのファイルやディレクトリの内容は以下の通りです。
- atcoder.sh: コンテスト生成用スクリプト
- run.sh: デバッグ用スクリプト(自動生成)
- .vscode/settings.json: Rustのvscode設定ファイル(自動生成)
./
├─compete.toml
├─template-cargo-lock.toml
├─atcoder.sh
├─abc193
│ ├─.vscode
│ │ └─settings.json
│ ├─Cargo.toml
│ ├─Cargo.lock
│ ├─run.sh
│ ├─src
│ │ └─bin
│ └─testcases
オリジナルテンプレート設定
テンプレート設定は、compete.toml
の[template]
で設定することができます。
デフォルトは以下の通りです。
自作のライブラリをスニペット設定してもよいですが、以下に貼り付けておくのも有りです!
src = '''
fn main() {
todo!();
}
テンプレートの一例です。
src = '''
#![allow(non_snake_case)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::comparison_chain)]
#![allow(clippy::nonminimal_bool)]
#![allow(clippy::neg_multiply)]
#![allow(dead_code)]
use itertools::Itertools;
use std::collections::{BTreeMap, BTreeSet, VecDeque};
use proconio::{
fastout, input,
marker::{Chars, Usize1},
};
const MOD: usize = 1e9 as usize + 7;
// const MOD: usize = 998244353;
// const MOD: usize = 2147483647;
#[macro_export]
macro_rules! max {
($x: expr) => ($x);
($x: expr, $( $y: expr ),+) => {
std::cmp::max($x, max!($( $y ),+))
}
}
#[macro_export]
macro_rules! min {
($x: expr) => ($x);
($x: expr, $( $y: expr ),+) => {
std::cmp::min($x, min!($( $y ),+))
}
}
#[derive(Default)]
struct Solver {}
impl Solver {
#[fastout]
fn solve(&mut self) {
// let mut stdin = LineSource::new(BufReader::new(io::stdin()));
// macro_rules! input(($($tt:tt)*) => (proconio::input!(from &mut stdin, $($tt)*)));
input! {
}
}
}
fn main() {
std::thread::Builder::new()
.stack_size(128 * 1024 * 1024)
.spawn(|| Solver::default().solve())
.unwrap()
.join()
.unwrap();
}
release設定
cargo compete
はデフォルトで、--release
が付与されていないので、Rust本来の実行速度で動作しません。
実行速度があまり問題にならないのではれば、不要ですが、cargo compete test
でTLEになってしまい、提出したらACした、ということが起こりえます。
そのため、基本的に以下のコマンドの通り、--release
を付与しておくことをオススメします。
※最初だけコンパイルに時間を要します
cargo compete test a --release
cargo compete submit a --release
いちいち--release
を付与するのが面倒であれば、Cargo.toml
に以下を追記することで、付与しなくてスクリプトもreleaseと同等のコンパイルをします。
コンテスト中に、この記述をするのはナンセンスなので、次項の通り、コンテスト生成用スクリプトにより自動化します。
[profile.dev]
opt-level = 3
コンテスト生成用スクリプト
通常コンテストのディレクトリを生成する際は以下のコマンドにより行います。
cargo compete new abc193
これを以下に置き換えます。
./atcoder.sh abc193
atcoder.sh
の中身は以下の通りです。
- コンテストのディレクトリを生成して、移動
- vscodeの設定ファイル作成(echoの中身を自分が好きなように設定、フォーマッターやリンターが不要な人は削除)
- デバッグ用スクリプト(windows用、Macだとパスが違うので編集が必要)
- releaseでコンパイルするために、
Cargo.toml
に設定を追記 - コンテストのディレクトリをvscodeで開く
# make contest directory and files
cargo compete new $1
cd $1
# make settings.json
mkdir .vscode
touch .vscode/settings.json
echo '{
"editor.formatOnSave": true,
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"rust-analyzer.checkOnSave.command": "clippy",
"rust-analyzer.checkOnSave.extraArgs": ["--", "-A", "clippy::needless_return"]
}
' >> .vscode/settings.json
# make run.sh
touch run.sh
echo '
p=`pwd`
dir=${p##*/}
p=${p///c/C:}
p=${p//\//\\}
p=${p}\\Cargo.toml
rustup run 1.42.0 cargo run --bin $dir-$1 --manifest-path $p
' >> run.sh
# add opt-level to Cargo.toml
echo '
[profile.dev]
opt-level = 3' >> Cargo.toml
# open vscode
code .
デバッグ用スクリプト
cargo compete test
を使用しないで、デバッグする際は以下のコマンドにより行いますが、以下の欠点があります。
- コマンドが長い
- Rustのバージョンがデフォルトで1.42.0でない場合、AtCoder指定の1.42.0で実行されない
cargo run --bin abc193-a
これを以下に置き換えます。
./run.sh a
前項のコンテスト生成スクリプトで自動生成されるデバッグ用スクリプトの内容は以下の通りです。
p=`pwd`
dir=${p##*/}
p=${p///c/C:}
p=${p//\//\\}
p=${p}\\Cargo.toml
rustup run 1.42.0 cargo run --bin $dir-$1 --manifest-path $p
Discussion