diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..731355c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,122 @@ +# -*- coding:utf-8-unix -*- + +[package] +name = "{{project-name}}" +version = "0.1.0" +authors = ["{{authors}}"] +edition = "2018" + +[[bin]] +name = "main" +path = "src/main.rs" + +[dependencies] +# AtCoder 2020年言語アップデート以降に使用できるクレート。 +# 次のページに各クレートについての細かい紹介があります。 +# https://github.com/rust-lang-ja/atcoder-rust-resources/wiki/2020-Update + +# 数値型の抽象化、多倍長整数、複素数、分数、及び整数型の拡張 +#num = "=0.2.1" +#num-bigint = "=0.2.6" +#num-complex = "=0.2.4" +#num-integer = "=0.1.42" +#num-iter = "=0.1.40" +#num-rational = "=0.2.4" +#num-traits = "=0.2.11" + +# `num-traits`の自動実装 +#num-derive = "=0.3.0" + +# NumPyの`ndarray`のような多次元配列 +#ndarray = "=0.13.0" + +# 線形代数 +#nalgebra = "=0.20.0" + +# (線形)代数の抽象化 +#alga = "=0.9.3" + +# libmのRust実装 +#libm = "=0.2.1" + +# 乱数 +#rand = { version = "=0.7.3", features = ["small_rng"] } +#getrandom = "=0.1.14" +#rand_chacha = "=0.2.2" +#rand_core = "=0.5.1" +#rand_hc = "=0.2.0" +#rand_pcg = "=0.2.1" + +# 乱数の分布の追加 +#rand_distr = "=0.2.2" + +# グラフ +#petgraph = "=0.5.0" + +# 挿入順を保持するhash table +#indexmap = "=1.3.2" + +# 正規表現 +#regex = "=1.3.6" + +# staticアイテムの遅延初期化 +#lazy_static = "=1.4.0" + +# `NotNan`, `OrderedFloat` +#ordered-float = "=1.0.2" + +# ASCII文字列 +#ascii = "=1.0.0" + +# permutation +#permutohedron = "=0.2.4" + +# スライスの拡張 +#superslice = "=1.0.0" + +# イテレータの拡張 +#itertools = "=0.9.0" + +# イテレータの拡張(一次元累積和と浮動小数点数の等差数列) +#itertools-num = "=0.1.3" + +# `BTreeMap`, `BTreeSet`, `HashMap`, `HashSet`のリテラル用マクロ +#maplit = "=1.0.2" + +# 即席enum `Either` +#either = "=1.5.3" + +# `BTreeMap`, `BTreeSet`, `HashMap`, `HashSet`, `Vec`の永続データ構造版 +#im-rc = "=14.3.0" + +# 可変長bit set +#fixedbitset = "=0.2.0" + +# 可変長bit set +#bitset-fixed = "=0.1.0" + +# 競技プログラミングの入出力サポートその1 +proconio = { version = "^0.3.6", features = ["derive"] } +# proconio は AtCoder のサーバー環境では 0.3.6 がインストールされていますが、 +# Rust Analyzer で型推論を可能にするなど、提出先での挙動を変えない範囲の改善が +# ありました。これらはバージョン 0.3 シリーズとして提供されているので、利便性の +# 観点から少し緩めに指定しておきます。ただし、万が一サーバー側と挙動が違うなど +# の問題があるようでしたら直接 0.3.6 を指定して利用してください。 +#proconio = { version = "=0.3.6", features = ["derive"] } + +# 競技プログラミングの入出力サポートその2 +#text_io = "=0.1.8" + +# 競技プログラミングの入出力サポートその3 +#whiteread = "=0.5.0" + +# 高速なハッシュ関数 +#rustc-hash = "=1.1.0" + +# ある長さまでは要素を「直に」持つ可変長配列 +#smallvec = "=1.2.0" + +# --------------------------------------------------------------------- + +[dev-dependencies] +cli_test_dir = "0.1" diff --git a/README.md b/README.md index 79ba6f1..2249515 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,166 @@ -# AtCoder Rust Base +# AtCoder Rust Base (`ja`) -このリポジトリは[AtCoder][atcoder]コンテスト(競技プログラミング)にRustで参加するためのCargoパッケージテンプレートです。 -パッケージの作成は[cargo-generate][cargo-generate-crate]で行います。 +このリポジトリには[AtCoder][atcoder]コンテスト(競技プログラミング)にRustで参加するためのCargoパッケージテンプレートが用意されています。 +パッケージは[cargo-generate][cargo-generate-crate]で作成します。 + +**この`README.md`では`ja`テンプレートの内容について説明します**。 +他のテンプレートについては[こちら][list-of-templates]をご覧ください。 [atcoder]: https://atcoder.jp [cargo-generate-crate]: https://crates.io/crates/cargo-generate +[list-of-templates]: https://github.com/rust-lang-ja/atcoder-rust-base/blob/master/README.md#用意されているテンプレート + + +## `ja`テンプレートの内容 + +- AtCoder 2019年言語アップデート後の環境向け +- Rust 1.42.0 + - `rustup`でインストールされていることを前提にしている + +**TODO** もう少し詳しく書く + + +## 使いかた + +### 準備:cargo-generateのインストール + +以下のコマンドでcargo-generateをインストールします。 + +#### Linux (Ubuntu 18.04) + +```console +$ sudo apt install libssl-dev pkg-config +$ cargo install cargo-generate +``` + +#### Windows 10 MSVC + +```console +$ cargo install cargo-generate +``` + +#### macOS Mojave 10.14 + +cargo-generateが依存しているopenss-sysクレートは、macOSに元から入っているOpenSSLライブラリのバージョンに対応していません。 +(OpenSSLのバージョンが低すぎる)  +そのOpenSSLライブラリを使おうとすると以下のようなエラーになります。 + +```console +error failed to run custom build command for `openssl-sys v0.9.47` +... + +It looks like you're compiling on macOS, where the system contains a version of +OpenSSL 0.9.8. This crate no longer supports OpenSSL 0.9.8. + +As a consumer of this crate, you can fix this error by using Homebrew to +install the `openssl` package, ... +``` + +エラーメッセージのおすすめにしたがって、[Homebrew][homebrew]で新しいバージョンのOpenSSLライブラリをインストールします。 + +```console +$ brew install openssl +``` + +cargo-generateをインストールします。 + +```console +$ cargo install cargo-generate +``` + +[homebrew]: https://brew.sh/ + + +### パッケージの生成 + +`cargo generate`コマンドでパッケージを生成します。 + +```console +$ cargo generate --name abc086c \ + --git https://github.com/rust-lang-ja/atcoder-rust-base \ + --branch ja +``` + +- `--name`: これから作成するパッケージの名前。好きな名前が付けられる。例:`abc086c` +- `--branch`: このテンプレートリポジトリのブランチ名。`ja`テンプレートを使うなら`ja`を指定する + + +### 解答となるプログラムの作成 + +1. 使用するクレートの選択 + - [`Cargo.toml`][cargo-toml-file]ファイルを開き`[dependencies]`セクションに書かれているクレートのなかで必要なものがあればコメントを外します。 + - 注意:AtCoderの環境では、これら以外のクレートは使用できません。またバージョンも固定されています。 + +1. 使用するクレートのドキュメントの生成 + - 必須ではありませんが、以下のコマンドで依存クレートのドキュメントをビルドし、Webブラウザで開いておくと便利でしょう。 + + ```console + $ cargo doc --open # ドキュメントのビルドし、ビルドできたらWebブラウザで開く + # または + $ cargo doc # ドキュメントのビルドのみ行う + ``` + +1. テストケースの作成 + - [`tests/sample_inputs.rs`](./tests/sample_inputs.rs)ファイルには、ひな型となるテストケースが用意されています。 + - AtCoderの問題文に書かれているサンプル入出力をこのファイルに書き写します。 + これにより`cargo test`でプログラムの動作が確認できるようになります(後述)。 + +1. プログラムの作成 + - [`src/main.rs`](./src/main.rs)に解答となるプログラムを書きます。 + +1. テストケースの実行 + - 以下のコマンドでテストケースを実行し、テストにパスすることを確認します。 + + ```console + $ cargo test -j 1 + ``` + + **実行例** + + ```console + $ cargo test -j 1 + ... + Finished dev [unoptimized + debuginfo] target(s) in 25.31s + Running target/debug/deps/main-aae3efe8c7e14c29 + + running 0 tests + + test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + + Running target/debug/deps/sample_inputs-946c74199de6e6a4 + + running 3 tests + No + test sample2 ... ok + Yes + test sample1 ... ok + No + test sample3 ... ok + + test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + ``` + - `-j`オプションはテストケース実行の並列数を指定し、デフォルト値はCPUの論理コア数です。 + `-j 1`を指定すると、テストケースが複数あるときに、それらを1つずつ順番に実行するようになります。 + - 上の例では`No`や`Yes`のようにプログラムからの標準出力を表示しています。 + もしテストケースが並列に実行されると複数のテストケースからの標準出力が混ざって分かりにくくなります。 + `-j 1`の指定は、このようなときに便利です。 -## 用意されているテンプレート -以下のテンプレートが用意されています。 +1. プログラムの提出 + - プログラムが完成したら`src/main.rs`の内容をAtCoderに提出します。 + `AC`を目指して頑張ってください。 -| 名前 | Rustバージョン | 内容 | -|:-- |:--:|:-- | -| [ja][ja-branch] | 1.35.0 | 標準的な内容のテンプレートに日本語のソースコードコメントを付けたもの。注意:2019年言語アップデート後の環境向け。Rust 1.15.1の環境では使用できない | -| [vendor-ja][vendor-ja-branch] | 1.35.0 | jaをベースに、依存するクレートのソースコードを`vendor`ディレクトリ配下に展開したもの。AtCoderの運営者が環境構築に使用できる。注意:Rust 1.15.1の環境では使用できない | +[cargo-toml-file]: ./Cargo.toml -使いかたについては、テンプレートの名前をクリックして表示されたREADMEを参照してください。 -If you want a template with English source code comments, please request it to us by filing [a GitHub issue][gh-issue]. +## 使用可能なクレート -[ja-branch]: https://github.com/rust-lang-ja/atcoder-rust-base/tree/ja -[vendor-ja-branch]: https://github.com/rust-lang-ja/atcoder-rust-base/tree/vendor-ja -[gh-issue]: https://github.com/rust-lang-ja/atcoder-rust-base/issues +AtCoderの環境では、[`Cargo.toml`][cargo-toml-file]にあらかじめ書かれているクレートのみが使用できます。 +それら以外のクレートを追加すると、手元ではコンパイルできてもAtCoderの環境ではコンパイルエラーになりますので注意してください。 +またクレートのバージョンも固定されており、変更できません。 ## ライセンス / License diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..a50908c --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +1.42.0 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7c76ee --- /dev/null +++ b/src/main.rs @@ -0,0 +1,22 @@ +// -*- coding:utf-8-unix -*- + +use proconio::input; + +// ABC086C - Traveling +// https://atcoder.jp/contests/abs/fasks/arc089_a + +fn main() { + input! { + n: usize, + mut plan: [(i32, i32, i32); n], // Vec<(i32, i32, i32)> + } + plan.insert(0, (0, 0, 0)); + let yes = plan.windows(2).all(|w| { + let (t0, x0, y0) = w[0]; + let (t1, x1, y1) = w[1]; + let time = t1 - t0; + let dist = (x1 - x0).abs() + (y1 - y0).abs(); + dist <= time && time % 2 == dist % 2 + }); + println!("{}", if yes { "Yes" } else { "No" }); +} diff --git a/tests/sample_inputs.rs b/tests/sample_inputs.rs new file mode 100644 index 0000000..5559ea7 --- /dev/null +++ b/tests/sample_inputs.rs @@ -0,0 +1,48 @@ +use cli_test_dir::*; + +const BIN: &'static str = "./main"; + +#[test] +fn sample1() { + let testdir = TestDir::new(BIN, ""); + let output = testdir + .cmd() + .output_with_stdin(r#"2 +3 1 2 +6 1 1 +"#) + .tee_output() + .expect_success(); + assert_eq!(output.stdout_str(), "Yes\n"); + assert!(output.stderr_str().is_empty()); +} + +#[test] +fn sample2() { + let testdir = TestDir::new(BIN, ""); + let output = testdir + .cmd() + .output_with_stdin(r#"1 +2 100 100 +"#) + .tee_output() + .expect_success(); + assert_eq!(output.stdout_str(), "No\n"); + assert!(output.stderr_str().is_empty()); +} + +#[test] +fn sample3() { + let testdir = TestDir::new(BIN, ""); + let output = testdir + .cmd() + .output_with_stdin(r#"2 +5 1 1 +100 1 1 +"#) + .tee_output() + .expect_success(); + assert_eq!(output.stdout_str(), "No\n"); + assert!(output.stderr_str().is_empty()); +} +