AtCoder 言語アップデート クレート個人的感想
2023-08-06 の 新ジャッジテストコンテスト -Algorithm- 以降から AtCoder で使える Rust のバージョンが 1.70.0 になり、以下のクレートが使えるようになりました。 それらを主観で使えそうとか雑にコメントしていく記事です。
ac-library-rs = "0.1.1"
once_cell = "1.18.0"
static_assertions = "1.1.0"
varisat = "0.2.2"
memoise = "0.3.2"
argio = "0.2.0"
bitvec = "1.0.1"
counter = "0.5.7"
hashbag = "0.1.11"
pathfinding = "4.3.0"
recur-fn = "2.2.0"
indexing = "0.4.1"
amplify = "3.14.2"
amplify_derive = "2.11.3"
amplify_num = "0.4.1"
easy-ext = "1.0.1"
multimap = "0.9.0"
btreemultimap = "0.1.1"
bstr = "1.6.0"
az = "1.2.1"
glidesort = "0.1.2"
tap = "1.0.1"
omniswap = "0.1.0"
multiversion = "0.7.2"
num = "0.4.1"
num-bigint = "0.4.3"
num-complex = "0.4.3"
num-integer = "0.1.45"
num-iter = "0.1.43"
num-rational = "0.4.1"
num-traits = "0.2.15"
num-derive = "0.4.0"
ndarray = "0.15.6"
nalgebra = "0.32.3"
alga = "0.9.3"
libm = "0.2.7"
rand = "0.8.5"
getrandom = "0.2.10"
rand_chacha = "0.3.1"
rand_core = "0.6.4"
rand_hc = "0.3.2"
rand_pcg = "0.3.1"
rand_distr = "0.4.3"
petgraph = "0.6.3"
indexmap = "2.0.0"
regex = "1.9.1"
lazy_static = "1.4.0"
ordered-float = "3.7.0"
ascii = "1.1.0"
permutohedron = "0.2.4"
superslice = "1.0.0"
itertools = "0.11.0"
itertools-num = "0.1.3"
maplit = "1.0.2"
either = "1.8.1"
im-rc = "15.1.0"
fixedbitset = "0.4.2"
bitset-fixed = "0.1.0"
proconio = "0.4.5"
text_io = "0.1.12"
rustc-hash = "1.1.0"
smallvec = "1.11.0"
ac-library-rs
ACL の Rust版ですね。大体 これ のドキュメントを読めば分かるはず
use ac_library::Dsu;
fn main() {
Dsu::new(10);
}
とかやれば使える
once_cell
1度しか初期化できない型を提供している。
static_assertions
定数や型に関するアサーションを提供している。コンパイル時にチェックされるらしい。
varisat
SAT ソルバー。なんで入ってるんだろう…?(2-SAT とか書くの楽なのかな?)。
この辺 読めば使えそう
use varisat::{ExtendFormula, Lit, Solver, CnfFormula};
fn main() {
let mut formula = CnfFormula::new();
let (a, b, c) = (Lit::from_dimacs(1), Lit::from_dimacs(2), Lit::from_dimacs(3));
formula.add_clause(&[a, b, c]);
formula.add_clause(&[!a, !b]);
formula.add_clause(&[!b, !c]);
formula.add_clause(&[!a, !c]);
let mut solver = Solver::new();
solver.add_formula(&formula);
let result = solver.solve();
assert_eq!(result.unwrap(), true);
let model = solver.model().unwrap();
eprintln!("{:?}", model);
// [-1, 2, -3]
}
もしかしたら文字列で渡すほうが用意しやすいかも?
let dimacs_cnf = b"1 2 3 0\n-1 -2 0\n-2 -3 0\n";
solver.add_dimacs_cnf(&dimacs_cnf[..]).expect("parse error");
memoise
関数をメモ化してくれる
use memoise::memoise;
#
#[memoise(n <= 100)]
fn fib(n: i64) -> i64 {
if n == 0 || n == 1 {
return n;
}
fib(n - 1) + fib(n - 2)
}
memoise
と書いたら Vec
、 memoise_map
と書いたら BtreeMap
でメモ化してくれるみたい。
ABC314 E をこれで解いてみた(ソースコード)。使い勝手良さそう。
argio
関数の入出力を stdio に変換するマクロらしい。内側では proconio
を使っているから proconio
と同じ感じで書けるらしい。たまに嬉しそう?
#[argio]
fn main(n: i32) -> i32 {
n * 2
}
bitvec
C++ にもある bitset
みたいに使えるやつっぽい。(これ系いつも使い方わかりません)。
こんな感じで使えるっぽい?
fn main() {
let mut bits = bitvec![usize, Msb0; 0; 20];
bits.set(0, true);
for c in [1 , 6, 7, 10] {
let mut shift = bits.clone();
shift.shift_right(c);
bits |= shift;
}
println!("{:?}", bits);
assert_eq!(bits[13], true);
}
counter
Python の counter を参考にしているらしい。 most_common とかがあるのは便利かも?
use counter::Counter;
fn main() {
let v = vec![1, 4, 2, 4, 3, 4, 4];
let counts = v.iter().collect::<Counter<_>>();
eprintln!("{:?}", counts);
assert_eq!(counts[&1], 1);
}
hashbag
unordered_multiset。contains で数がとれるらしい。
pathfinding
グラフアルゴリズムが入っているらしい。
- A*
- BFS
- Brent
- DFS
- Dijkstra
- Edmonds Karp
- Floyd
- Fringe
- IDA*
- IDDFS
- strongly connected components
- topological sorting
- Yen
- connected components
- Kruskal
- Kuhn-Munkres
recur-fn
ラムダ再帰ができるようになるやっぽい
use recur_fn::{recur_fn, RecurFn};
fn main() {
let fib = recur_fn(|fib, n: i32| {
if n <= 1 {
n
} else {
fib(n - 1) + fib(n - 2)
}
});
println!("{}", fib.call(10));
}
indexing
unchecked な indexing ができるらしい。ライブラリ作りには嬉しそう
amplify
マクロとか追加するやつ。
こういうことができるらしい。(BtreeMap の宣言)
#[macro_use]
extern crate amplify;
let map = bmap! {
s!("key") => 5,
s!("other_key") => 10
};
easy_ext
extension-trait-conventions をもっと簡単に記述するためのマクロ
multimap
HashMap を使った multimap
btreemultimap
BtreeMap を使った multimap
bstr
バイト文字列のライブラリ。
az
型キャストした時にチェックしてくれたりする。(-1).wrapping_as::<u32>()
とかすると 1u32.wrapping_neg()
が得られる。
glidesort
安定ソート。早いらしい。
tap
tap
とか pipe
とかを間に挟み込める。tap
はデバッグとかに使えて、 pipe
は変換とか挟み込める。
消し忘れそう…。
use tap::Tap;
fn main() {
let n = 13;
let odd_sum = (0..n).filter(|&x| x % 2 == 1)
.tap(|x| println!("odd: {:?}", x))
.sum::<usize>();
println!("{}", odd_sum);
}
swap
参照が重複して std::mem::swap
できないやつも swap できるようにするマクロ。
fn main() {
let mut a = vec![vec![1, 2, 3], vec![4, 5, 6]];
// std::mem::swap(&mut a[0][1], &mut a[1][3]); // これはダメ
omniswap::swap!(&mut a[0][1], &mut a[1][3]);
}
multiversion
CPUによって関数の実装を変えたりできるやつ。
num
整数色々。num-bigint
、 num-complex
、num-integer
とか色々ある。
整数範囲の sqrt
とか便利。
ndarray
行列ライブラリ
nalgebra
行列ライブラリ
alga
代数系トレイト。Monoid とか入ってる
libm
libm の Rust 実装。 f32, f64 の便利関数が色々
rand
乱数関連の色々
getrandom
OS の乱数生成器のインターフェース
petgraph
グラフライブラリ。前のバージョンでも入っていた。
indexmap
なんか色々機能のある HashMap と HashSet
regex
正規表現。前のバージョンでも入っていた。
lazy_static
遅延評価のマクロ。前のバージョンでも入っていた。
ordered-float
Float のラッパー。前のバージョンから入っていたらしい。Float をソートするときに楽できる。
let mut v = [OrderedFloat(NAN), OrderedFloat(2.0), OrderedFloat(1.0)];
v.sort();
assert_eq!(v, [OrderedFloat(1.0), OrderedFloat(2.0), OrderedFloat(NAN)]);
ascii
ASCII文字列・文字を扱うやつ。前のバージョンでも入っていた。
permutohedron
next_permutation
とかを提供している。前のバージョンでも入っていた。
superslice
超便利なやつ。 lower_bound
とかを提供している。前のバージョンでも入っていた。
use superslice::*;
let b = [1, 3];
assert_eq!(b.lower_bound(&1), 0);
assert_eq!(b.upper_bound(&1), 1);
assert_eq!(b.equal_range(&3), 1..2);
itertools
これも超便利。 iter に対して色々できる。前のバージョンでも入っていた。
maplit
HashMap とかがマクロで定義できるやつ。amplify と近いかも
im-rc
永続データ構造が使える。色々なデータ構造が入ってる。
fixedbitset
bitset
bitset-fixed
bitset
proconio
競プロの IO を楽にするやつ。
rustc-hash
高速で非暗号なハッシュ
smallvec
smallvec