Skip to content

Commit 5e12106

Browse files
committed
Fix markdown styling
1 parent f981677 commit 5e12106

12 files changed

+40
-3
lines changed

Diff for: src/atcoder-env/compiling-and-running-using-cargo.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- -*- coding:utf-8-unix -*- -->
2+
13
# [cargo] ファイルレイアウトとコンパイルの流れ
24

35
選手がRustプログラムを提出すると、その内容がジャッジサーバ上のファイルシステムに書き出されます。
@@ -21,7 +23,8 @@ $HOME # ユーザのホームディレクトリ
2123

2224
以上でCargoプロジェクトが整いました。
2325

24-
# コンパイルコマンド
26+
27+
## コンパイルコマンド
2528

2629
ツールチェインのインストールのページで説明したように、コンパイルを実行するシェルに以下の環境変数が設定されている必要があります。
2730

Diff for: src/atcoder-env/compiling-and-running-using-rustc.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- -*- coding:utf-8-unix -*- -->
2+
13
# [rustc] ファイルレイアウトとコンパイルの流れ
24

35
選手がRustプログラムを提出すると、その内容がジャッジサーバ上のファイルシステムに書き出されます。
@@ -25,7 +27,7 @@ $HOME
2527
```
2628

2729

28-
# コンパイルコマンド
30+
## コンパイルコマンド
2931

3032
ツールチェインのインストールのページで説明したように、コンパイルを実行するシェルに以下の環境変数が設定されている必要があります。
3133

Diff for: src/atcoder-env/installing-rust-crates.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- 例:標準ライブラリのハッシュ関数はDoS攻撃を避けるために暗号強度があり、計算量が多い。
2121
競技プログラミングでは暗号強度は求められず、より計算量の少ないハッシュ関数で十分
2222

23+
2324
### AtCoder運営者様へのお願い
2425

2526
対象クレートの一覧は[このページ][crates-2019]にあります。
@@ -38,6 +39,7 @@
3839
`cargo build`コマンドを実行すると、Cargoはそれらのクレートのソースコードをダウンロードし、適切なオプションと共に`rustc`を実行することでクレートをコンパイルします。
3940
クレートのソースコードは`$CARGO_HOME/registory/src`にダウンロードされ、コンパイル済みのクレート(`rlib`ファイル)は`Cargo.toml`が置かれたディレクトリを起点とする相対ディレクトリ`./target/release/deps`配下に出力されます。
4041

42+
4143
### 一般的な開発時のファイルレイアウト
4244

4345
```console
@@ -63,6 +65,7 @@ $HOME # ユーザのホームディレクトリ
6365

6466
まず、今回は各ファイルを以下のように配置し、クレートのコンパイルは導入時に済ませておくことにします。
6567

68+
6669
### AtCoderジャッジサーバでのファイルレイアウト(導入時に配置するもの)
6770

6871
```console
@@ -82,6 +85,7 @@ $RUST_HOME (/usr/local/lib/rust)
8285

8386
そしてジャッジの際には[以前説明した](./supported-environment.md#一般的なrustプログラム開発環境との違い)Cargoを利用する方法と`rustc`を利用する方法のいずれかを利用してコンパイルします。
8487

88+
8589
### [cargo] AtCoderジャッジサーバでのファイルレイアウト(ジャッジの際に作成するもの)
8690

8791
```console
@@ -96,6 +100,7 @@ $HOME # ユーザのホームディレクトリ
96100
└-- atcoder-rust-base # コンパイル、リンク済みの実行ファイル
97101
```
98102

103+
99104
### [rustc] AtCoderジャッジサーバでのファイルレイアウト(ジャッジの際に作成するもの)
100105

101106
Cargoを使用せず、`rustc`に適切なオプション(ライブラリ検索パスなど)を与えて実行することで、事前にコンパイルしておいた`rlib`ファイルとリンクさせます。
@@ -343,6 +348,7 @@ _108 = {package = "whiteread",version = "=0.4.4",default-features = false,featur
343348
[the-cargo-book-platform-specific-dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies
344349
[the-cargo-book-specifying-dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies
345350

351+
346352
## クレートのコンパイル
347353

348354
クレートをコンパイルしましょう。
@@ -371,4 +377,3 @@ $ find target/release/deps/ -type f | egrep -c '\.(rlib|so)$'
371377
66
372378
# ↑ 上の数字を確認
373379
```
374-

Diff for: src/atcoder-env/installing-rustc-dep-option-generator.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ $ sudo apt install -y libssl-dev
1919

2020
なお`libssl-dev``rustc-dep-option-generator``cargo`をライブラリとして用いているために必要ですが、このツールではその機能は使いません。ツール実行時のネットワーク・アクセスは不要です。
2121

22+
2223
## ツールのインストール
2324

2425
`cargo install`コマンドでインストールします。

Diff for: src/atcoder-env/supported-environment.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# 本章で想定している環境
44

5+
56
## 用語
67

78
まずは用語を整理します。本章で用いる用語には以下のものがあります。

Diff for: src/introduction.md

+12
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ AtCoderは、オンラインで参加できるプログラミングコンテス
2525

2626
AtCoderで使える言語は非常にたくさんあります。どの言語を使ってもよいですし、問題によって使い分けても構いません。その中でなぜRustを使うのか、そのメリットとデメリットをまとめてみました。できるだけ一般論で比較するよう心がけますが、競技プログラミングにおけるC++人口がそれなりに多いことと、Rustはその特性上C++と比較されることが多いので、具体的にC++との比較になっている部分も多くあります。
2727

28+
2829
### メリット
2930

31+
3032
#### 高速である
3133

3234
AtCoder含め、競技プログラミングでは「実行時間制限」とよばれるものがあります。この時間内にプログラムの実行が終わらないと「TLE (Time Limit Exceeded)」という判定が付いて誤答扱いとなります。多くの場合は想定されている解法であれば多少の余裕をもって解けるように設定されていますが、非常にたくさんの言語が使える都合上全ての言語で公平になるようにはできません。遅い言語に合わせて設定すると速い言語では強引な解法でゴリ押しできてしまうことがありますし、速い言語に合わせると遅い言語では想定されている解法でも通せないということになります。いずれにせよ、基本的には速い言語であるほうが計算時間的には有利です。 (もちろん遅い言語と言われるものにも、例えば書き易さであったり、ライブラリが充実していたり、なにかしらのメリットがあるはずです。どちらかが絶対的に有利ということではありません。)
3335

3436
Rustは最速と言われるC/C++並みに速いとされていますので、(少なくともAtCoderでは) 速度面で不利になることはないと言えるでしょう。
3537

38+
3639
#### 信頼性が高い
3740

3841
信頼性は、ここではRustの[公式トップページ](https://www.rust-lang.org/)に倣いメモリ安全性、スレッド安全性、バグの起こしにくさであるとします。競技プログラミングで特に大事になってくるのはメモリ安全性とバグの起こしにくさです。
@@ -97,6 +100,7 @@ stack backtrace:
97100
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
98101
```
99102

103+
100104
#### 多くの問題をコンパイル時に発見できる
101105

102106
RustはC/C++並みの速度を確保するため、実行時にやらなければいけないことをなるべく減らす方針の言語です。たとえば先ほど触れたように、多くの言語にあるガベージコレクタがありません。それだけならばC++と変わりありませんが、速度と安全性を両立させるためにRustではできるだけ多くのことをコンパイル時に確認する仕組みになっています。C++が受け入れてしまうような危険なコードもコンパイルエラーにします。
@@ -136,6 +140,7 @@ let x: i32 = s.into_iter().sum();
136140

137141
ジェネリクスとトレイトの仕組みも強力です。たとえばジェネリックな関数が型変数`T`をもつとき、この`T`のとりうる型を特定のトレイト (=機能一覧) を実装しているものだけに制限することができます。逆に`T`に対してできることはその特定のトレイトが定める機能のみです。従って、一度コンパイルが通った関数はその制約を満たす限りのどのような`T`を与えても関数の内部でコンパイルエラーとなることはありません。特にライブラリを整備するにあたってはこれはとてもありがたいことです。実際に使ってみなくても、コンパイルさえ通れば、将来的に作られうるどんなユーザー定義型を与えようともその関数が正しく呼び出せることが保証されます。C++のテンプレートなどでは実際に具体的な型を与えて始めて様々な検証をするので、使う段階になってからでないとエラーが発見できません。このことは、後述するコンパイルエラーの分かりやすさにも繋がっています。
138142

143+
139144
#### コンパイルエラーが分かりやすい
140145

141146
これは少々主観的な話になるのかもしれませんが、Rustのコンパイルエラーは読みやすく分かりやすいという評判があります。実際にコンパイルエラーが発生したとき、まずエラーが起きた場所はもちろんとして、エラーが関連する他の場所 (例えば以前に借用された場所など) などをアスキーアート的な手法で視覚的に分かりやすく表示してくれます。さらに、なぜそれが間違っているのか/それをどのように修正することができるかのヒントが提示されることもあります。例えば、先ほどのエラー全体は次のようになっていました。
@@ -185,6 +190,7 @@ fn main() {
185190
(以下略)
186191
``````
187192

193+
188194
#### 抽象化のための機能を数多く備えている
189195

190196
例えば次のようなさまざまな機能があります。Rustは後発の言語ですので、他のプログラミング言語に備わっている優れた機能も参考にして多数の機能が導入されています。
@@ -268,6 +274,7 @@ fn main() {
268274

269275
また、変数の個数を抑止するという効果もあります。block expression等と適宜組み合わせることで変数の数やスコープはさらに小さく保つことができ、多少関数の実装が長くなっても見通しが悪くなりにくいと言えます。競技プログラミングではmain関数が長くなりがちなので一層嬉しいのではないでしょうか。
270276

277+
271278
#### ゼロコスト抽象化を追求している
272279

273280
Rustの言語デザインやライブラリは、一定の使いやすさを実現しつつも、使いやすさのために実行時の高速性を犠牲にはしないという**ゼロコスト抽象化** (_zero-cost abstraction_)を追求しています。
@@ -276,8 +283,10 @@ Rustの言語デザインやライブラリは、一定の使いやすさを実
276283

277284
このことは「簡潔な構文や関数によってその機能が必要とするコストを隠してしまう」ことを避けているとも言えます。つまり、本当にパフォーマンスが必要なときに最適化を検討するべき「コスト」の部分が明確化されているということでもあります。
278285

286+
279287
### デメリット
280288

289+
281290
#### 現れる概念が比較的難しい
282291

283292
先に見たように、Rustでは、いままで他の言語ではコンパイラが検証していなかったようなことをコンパイル時に検証します。そのためにRustでは所有権や借用をはじめとする独特の概念が導入されており、それらの概念の理解そのものが難しいとされることも多いようです。これらの概念が課す多数のルールがなぜ存在するのかを理解することは、仕組みをある程度理解していなければ難しいものです。
@@ -286,6 +295,7 @@ Rustの言語デザインやライブラリは、一定の使いやすさを実
286295

287296
Rustが課すルールにも理由がありますので、そういった事情について意識的に考えることは他の言語や競技プログラミング以外の文脈でも活きる有意義なものではあると思います。単にAtCoderである程度の競技プログラミングをするだけであれば、C#やJavaといった言語でもほぼ正解できるよう調整されているようなので、どちらを取るかは好みといっていいかもしれません。
288297

298+
289299
#### 素早く書くことにはあまり向かない仕様
290300

291301
Rustの安全指向や標準ライブラリの設計方針などは、時間をかけて大規模なプログラムを書くときや堅牢なプログラムを書くときには非常に役に立ちます。一方で競技プログラミングでは、一般のプログラミングと異なり、次のような特徴があります。
@@ -341,12 +351,14 @@ fn main() {
341351
342352
Rustで参加する競技プログラマーの中には、こうした煩雑さを改善するためのマクロやヘルパ関数 (もっと便利に標準入力がとれるようにするなど) を定義し、テンプレート (ひな型) として用意している方もいます。インターネット上で公開されている方もいらっしゃいますし、過去のコンテストでの上位Rust参加者の提出などをのぞいてみると、いろいろと参考になるかもしれません。
343353
354+
344355
#### 標準ライブラリが小さい
345356
346357
Rustは比較的新しい言語ですので、インターネット接続環境を前提にしたパッケージ管理システムCargoを標準で持ちます。このため、言語の成長とクレートやRustエコシステムの成長を分離することを目的に、Rustは標準ライブラリを最低限の抽象化とインターフェースとして位置付け、できるだけ小さく保ち続けてきました。かつて標準ライブラリの一部だったり本体にバンドルされていたライブラリ (`num`, `rand`, `regex` など) を積極的に分離することさえしています。ユーザーはCargoを使えば、使いたいパッケージを[crates.io](https://crates.io)からいつでも自由にダウンロードできます。
347358
348359
(TODO: クレートが導入されたかどうか追記)
349360
361+
350362
#### コンパイル時間が長くなりがち
351363
352364
様々な解析をコンパイル時に行う都合上、コンパイル時間が長めにかかる傾向があります。Rustではコンパイル速度を速くすることはあまり重要視されていません。特に手元で提出をテストする際、外部クレートを利用するならその外部クレートのビルドも実行することになります。二回目以降のビルドではビルドキャッシュを利用するためコンパイルする必要はありませんが、初回の実行では利用する外部クレートによっては数分単位の時間をとられる可能性があります。つまり、素早く書き上げたコードを手元で軽く実行してみることにすら時間をとられてしまい、提出時刻が数分遅れてしまうということがあり得ます。結果的に手元でコンパイルが通るかどうかをチェックする時間すら惜しいとなってしまうと本末転倒です。なお、外部ライブラリを含むパッケージをコンテスト開始前に一回ビルドしておいて、競技時はそのフォルダをコピーして編集するというふうにすれば回避できます。

Diff for: src/participate/before-contest/choose-crates.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66

77
先にも軽く触れた通り、依存クレートのコンパイルにはそれなりの時間がかかります。コンテストが始まってから最初の問題の提出前に実行するとなるとそれなりのタイムロスになります。そこで次の二つのことをコンテスト開始前に行ってしまい、コンテスト開始後になるべくスムーズに行動できるよう準備しておきましょう。
88

9+
910
## 利用するクレートの選択
1011

1112
これは事前準備時間を短くする、またはビルドディレクトリのディスク容量を減らすことに効果があります。
1213

1314
すべての依存クレートを有効化すると、スペックや環境にもよりますが、初回のコンパイルに数分かかるようになり、ビルドキャッシュも数百 MB (メガバイト) になります。ただし二回目以降のコンパイル時間やコンパイル後のバイナリの実行速度には影響しません。すなわち、競プロとして AtCoder 上で不利になるようなことはありません。したがって、最初にすべてのクレートを有効にしてしまったほうがコンテスト中の自由度は高くなります。このあたりのバランスはご自分のパソコンのリソースと相談して選択してください。
1415

16+
1517
## 事前コンパイル
1618

1719
利用するクレートの選択を終えたら、次は事前コンパイルを行います。
@@ -37,6 +39,7 @@ $ cargo build
3739

3840
> Note: ここでは `cargo build` としてデバッグモードでのビルドを行いました。実際の AtCoder では `--release` オプションをつけて実行速度を最適化するのですが、これをつけるとさらにビルド時間が伸びてしまうことや、デバッガによるデバッグがしづらくなることなどのデメリットがあります。加えて、手元の環境ですることはサンプルケースレベルの比較的小さいサイズの入力を試す程度であることが多いため、速度を最適化する必要性もさほどないことが多いのではないでしょうか。一方、手元でもリリースビルドでテストすることがあるという方は、この段階で `cargo build --release` も加えて実行しておくことをおすすめします。そうでないとコンテスト中にリリースビルド用の依存クレートのコンパイルが行われ、多くの時間を取られてしまいます。
3941
42+
4043
## (オプション) Rust Language Server の事前準備
4144

4245
> Note: この手順は Rust Language Server (RLS) を利用しない方は必要ありません。

Diff for: src/participate/before-contest/generate-project.md

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
では、実際にプロジェクトを生成していきます。
1414

15+
1516
## `cargo-generate` をインストールしている場合
1617

1718
`cargo generate` コマンドをインストールしている場合は、次のようにコマンドを実行してプロジェクト名を入力すれば AtCoder での環境と同様の環境のプロジェクトが生成できます。
@@ -27,6 +28,7 @@ Done! New project created /path/to/project/abc000
2728

2829
> Note: ここで生成されるプロジェクトはサンプルとして [AtCoder Beginner Contest 086 C - Traveling](https://atcoder.jp/contests/abc086/tasks/arc089_a) の解答例とサンプルケースのテスト方法例が書かれてます。テンプレートを自分向けにカスタマイズしたい場合は、リポジトリをフォークするなどして編集し、それを URL に指定して生成させることもできます。
2930
31+
3032
## `cargo-generate` をインストールしていない場合
3133

3234
まずは空のプロジェクトを作成します。

Diff for: src/participate/during-contest/submit.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- -*- coding:utf-8-unix -*- -->
2+
13
# プログラムの提出
24

35
**TODO** このページは書きかけです。

Diff for: src/participate/during-contest/test.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- -*- coding:utf-8-unix -*- -->
2+
13
# プログラムのテスト
24

35
一通り書き終わったと思ったら、提出前にまずは一度サンプルケースで答えが合うかどうかを確認してみましょう。コマンド プロンプトまたは端末を開いてプロジェクトフォルダに移動して、次のようなコマンドを実行します。

Diff for: src/participate/during-contest/write-program.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- -*- coding:utf-8-unix -*- -->
2+
13
# プログラムの作成
24

35
**TODO** このページは書きかけです。

0 commit comments

Comments
 (0)