Skip to main content
Rustで楽しむ
競技プログラミング
(株)スリーダム 吉元佑介 (@yoshrc_public)
[自己紹介]
name = "Yusuke Yoshimoto"
age = 27
job-title = "Full-stack Engineer"
preferred-languages = ["Rust", "Python"]
atcoder.rate = 1168
contact.twitter = "@yoshrc_public"
Rustは競プロで使えるか
- C++でよくね?
- Python楽でいいよ
Rustは競プロで使えるか
競プロこそRust
- C++でよくね?
- Python楽でいいよ
Rustのここが強い
- C++のごとき実行速度
- 正義
- Scalaのごとき高度な抽象化能力
- 「競プロコピペ」を自作しやすい
Rustでつくる「競プロコピペ」
- 入力読み込み
- 最新のRustの機能をAtCoderで使う
- 便利メソッドを生やす
- データ構造
謹製コピペコード 
https://yoshrc.github.io/rust-atcoder-snippets/atcoder_snippets/index.html
Rustでつくる「競プロコピペ」
- 入力読み込み
- 最新のRustの機能をAtCoderで使う
- 便利メソッドを生やす
- データ構造
謹製コピペコード 
https://yoshrc.github.io/rust-atcoder-snippets/atcoder_snippets/index.html
やりたいこと
スライスから、すべての順列を生成する
let mut perms = [1, 2, 3].permutations().collect();
// permsは、以下のものを生成するイテレータ
// [1, 2, 3], [1, 3, 2],
// [2, 1, 3], [2, 3, 1],
// [3, 1, 2], [3, 2, 1]
実装
pub trait SliceExt<T> {
fn permutations(&self) -> Permutations<T>;
}
実装
pub trait SliceExt<T> {
fn permutations(&self) -> Permutations<T>;
}
impl<T> SliceExt<T> for [T] {
fn permutations(&self) -> Permutations<T> { … }
}
最後に
- C++でなくても、競プロは楽しめる
- Rustを使えば、汎用的なプログラミング技術が向上する
- メモリ安全
- ライブラリ作成
- 関数型プログラミング
Rustで競プロ、やろうよ!
没スライド
問題点:コピペがめんどい
問題点:コピペがめんどい
cargo-snippetを使う
すばらしきcargo-snippet
すばらしきcargo-snippet
すばらしきcargo-snippet
没スライド1
嵌ったとこ
借用
- Rustで問題を解こうとすると、イテレータを多用する
- イテレータメソッドで参照を戻すのがなかなか一発で書
けない
どこが間違ってる?
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|n| n >= min).count()
}
どこが間違ってる?
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|n| n >= min).count()
}
コンパイラ様に従ってみる
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|n| n >= &&min).count()
}
コンパイラ様に従ってみる
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|n| n >= &&min).count()
}
通る
より素直なコード
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|&&n| n >= min).count()
}
より素直なコード
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|&&n| n >= min).count()
}
より素直なコード
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|&&n| n >= min).count()
}
より素直なコード
fn count_ge_min(nums: &[u8], min: u8) -> usize {
nums.iter().filter(|&&n| n >= min).count()
}
没スライド2
Rustでつくる「競プロコピペ」
- 入力読み込みマクロ
- トレイトで最新のRustの機能をAtCoderで使う
- AtCoderのRustバージョン:1.15.1 超古い
- Iterator::step_by, Iterator::flatten, dbgマクロ …
- イテレータに便利メソッドを生やす
- 全部文字列化して連結
- データ構造を作る
- List, Union-Find …
謹製コピペコード 
https://atcoder.jp/contests/abc118/tasks/abc118_b
C++だとこんなに大変
https://atcoder.jp/contests/abc118/tasks/abc118_b
素のRustだと地獄
https://atcoder.jp/contests/abc118/tasks/abc118_b
私のスニペットでは
read!(n = u8, m = u8);
let k_a = readx::<(u8, Vec<u8_>)>();
私のスニペットでは
read!(k = u8, m = u8);
let k_a = readx::<(u8, Vec<u8_>)>();
私のスニペットでは
read!(n = u8, m = u8);
let k_a = readx::<(u8, Vec<u8_>)>();
assert_eq!(n, 3); assert_eq!(m, 4);
assert_eq!(k_a, vec![
(2, vec![0, 2]), (3, vec![0, 1, 2]), (2, vec![2, 1])
]);