Rustで競プロ（のセッティング）

Rust、使ってみたいなぁって思って、いつもやってるAtCoderで試してみようと思いました。

[はじめに - AtCoderコンテストにRustで参加するためのガイドブック](https://doc.rust-jp.rs/atcoder-rust-resources/introduction.html)

を参考に、テストのあたりを改良してみました。実際に解くのはまだやってないです……

## いろいろインストール

上記を参考にRustをインストール。さらに[cargo-generateのインストール（同ガイドブック。以下略）](https://doc.rust-jp.rs/atcoder-rust-resources/installation/cargo-generate.html)をします。

ガイドに従って雛形のプロジェクトをゲットします

```
$ cargo generate --git https://github.com/rust-lang-ja/atcoder-rust-base --branch ja
🤷  Project Name: abc000
🔧   Creating project called `abc000`...
✨   Done! New project created /Users/ユーザー/programing/Rust/abc000
```

`Project Name: `のあとの`abc000`は自分で入力。

```
$ cd abc000
```

移動。

### 中身

- abc000/src/main.rs<br>
ここに解答を書く。
- abc000/tests<br>テスト関係。主にここをいじる

## カスタマイズ

[テストケースの作成](https://doc.rust-jp.rs/atcoder-rust-resources/participate/during-contest/write-tests.html)のところに、Rustのテスト機能を使ってテストケースを試す方法が載ってます。ただ、テストケースがプログラム中に書き込んであって ちょっとカッコ悪い/コピペする時位置調整がめんどい のでファイルから読み込むようにします。

[rust: ファイル読み書き - nju33](https://nju33.com/rust/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E8%AA%AD%E3%81%BF%E6%9B%B8%E3%81%8D) を参考に`abc000/tests/sample_inputs.rs`を以下のように書き換えます。

```rust
use std::fs;
use cli_test_dir::*;

#[test]
fn sample() {
  let input = fs::read_to_string("tests/input.txt").unwrap();
  let output = fs::read_to_string("tests/output.txt").unwrap();

  let testdir = TestDir::new("main", "");
  let res = testdir.cmd()
    .output_with_stdin(input)
    .tee_output()
    .expect_success();
  assert_eq!(res.stdout_str(), output);
  assert!(res.stderr_str().is_empty());
}
```

途中の`.tee_output()`は、出力をテスト結果画面に出力するオプション、のようなものなので出力が長いとき等は削るのもあり。

さらに、入出力サンプルを入れるファイルを`abc000/tests/input.txt`・`abc000/tests/output.txt`と作成します。ガイドライン通りに雛形をゲットしているとABC086 - [C - Traveling](https://atcoder.jp/contests/abc086/tasks/arc089_a)の解答コードが入っているので、それに合わせて

```input.txt
2
3 1 2
6 1 1

```
```output.txt
Yes

```
とします。（特にoutput、最後の改行をやらないと一致判定で失敗するので注意）

## お試し

テストしてみます。

```
$ cargo build
```

これはこのプロジェクトを使う前準備的なもの、らしい。proconioを使えるようにしたりする。

```
$ cargo test
   Compiling abc000 v0.1.0 (/Users/ユーザー/programing/Rust/abc000)
    Finished test [unoptimized + debuginfo] target(s) in 1.64s
     Running target/debug/deps/main-028731574152944b

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/sample_inputs-c49f316d7d463d6e

running 1 test
Yes
test sample ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

```

サンプルの通過が判定できました！あとは各ケースをコピペすればいい。`ctrl+A``ctrl+V`で全体を上書きできるので楽。

## さらに改良

一致判定はしないで、単に出力をしてみたいときもあるので`abc000/tests/sample_inputs.rs`を書き換えます。

```rs
use std::fs;
use std::io::Write; //new!!
use cli_test_dir::*;

#[test]
fn sample() {
  let input = fs::read_to_string("tests/input.txt").unwrap();
  let output = fs::read_to_string("tests/output.txt").unwrap();

  let testdir = TestDir::new("main", "");
  let res = testdir.cmd()
    .output_with_stdin(input)
    .tee_output()
    .expect_success();
//assert_eq!(res.stdout_str(), output); ここじゃなくて
  assert!(res.stderr_str().is_empty());

  //new!!
  let mut file = fs::File::create("tests/view.txt").unwrap();
  write!(&mut file, "{}", res.stdout_str()).unwrap();

  assert_eq!(res.stdout_str(), output); //後ろに回す
}
```

[Rust - ファイルに書き込む | rust Tutorial](https://riptutorial.com/ja/rust/example/4276/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%80) を参考にしました。出力を`abc000/tests/view.txt`に書き出してくれます。

テストはエラーが出た時点で終了してしまうので、`output.txt`との一致判定は最後に回しました。とにかく`view.txt`に出力して欲しいので。

## おしまい

Rust、入力がめっちゃめんどくさい雰囲気だったんですけどproconioなるクレート（ライブラリ的な？）のおかげで楽にできます。ありがてぇ。

## 参考

- [AtCoderコンテストにRustで参加するためのガイドブック](https://doc.rust-jp.rs/atcoder-rust-resources/introduction.html)
- [rust: ファイル読み書き - nju33](https://nju33.com/rust/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E8%AA%AD%E3%81%BF%E6%9B%B8%E3%81%8D)
- [Rust - ファイルに書き込む | rust Tutorial](https://riptutorial.com/ja/rust/example/4276/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%80)