-
Notifications
You must be signed in to change notification settings - Fork 3
Jan 2023 Language Update ライブラリ案
このページは誰でも編集できます。
- 2023年環境に要望するクレート
-
2020年環境のクレート
-
num
- num-bigint
- num-complex
- num-integer
- num-iter
- num-rational
- num-traits
- num-derive
- ndarray
-
nalgebra
- alga
- libm
-
rand
- getrandom
- rand_chacha
- rand_core
- rand_hc
- rand_pcg
- rand_distr
- petgraph
- indexmap
- regex
- lazy_static
- ordered-float
- ascii
- permutohedron
- superslice
- itertools
- itertools-num
- maplit
- either
- im-rc
- fixedbitset
- bitset-fixed
- proconio
- text_io
whiteread- rustc-hash
- smallvec
-
num
c03e2cab25a5997ed00674fee5f821e5a5433b42
(Crates.ioにまだアップロードしていない)
- ac-libraryのRust実装。 (@qryxip)
- このままでもライブラリとしては機能するとはいえ、Crates.ioへのアップロードを含めまだ色々やることがあるため、急いでやっていく。 (@qryxip)
v1.17.1
-
lazy_staticと同じく、グローバル変数を定義できる。 (@qryxip)
use std::{collections::HashSet, sync::Mutex}; use once_cell::sync::Lazy; static SET: Lazy<Mutex<HashSet<i32>>> = Lazy::new(|| Mutex::new([0, 1, 2].into()));
-
lazy_staticよりも今はこちらの方が使われているはず。また今標準ライブラリに入りかけている。 (@qryxip)
-
とはいえ今は
Mutex
がconst文脈で用意できたりするので、利用する機会は減ってるかもしれない。 (@qryxip)use std::{collections::BTreeSet, sync::Mutex}; // 中身を入れるのは非const文脈じゃないと無理 SET.lock().unwrap().extend([0, 1, 2]); static SET: Mutex<BTreeSet<i32>> = Mutex::new(BTreeSet::new());
v1.1.0
-
型の性質やconst文脈での真偽値を、コンパイル時にassertできる。 (@qryxip)
use static_assertions::{assert_impl_all, const_assert_eq}; // u16はusizeに変換可能である assert_impl_all!(u16: Into<usize>); // 1+1=2である const_assert_eq!(1 + 1, 2);
-
その性質上手元でさえ動けばいいので、AtCoder側に入れなくてもこうすればいいのでは?と思わなくもない。 (@qryxip)
// 手元のコードエディタではエラーがちゃんと出て、かつAtCoder側でcargo buildするときは無視される #[cfg(test)] const _: () = { use static_assertions::{assert_impl_all, const_assert_eq}; // u16はusizeに変換可能である assert_impl_all!(u16: Into<usize>); // 1+1=2である const_assert_eq!(1 + 1, 2); };
v0.2.2
- SATソルバー。 (@qryxip)
- まあ一応提案するだけした方がいいかもしれない? (@qryxip)
v0.3.2
- @tanakh氏製の、競プロ用途に特化したメモ化ライブラリ。 (@qryxip)
- cachedがよくメンテされているようだが、上記のブログの通りAtCoderには向かないかもしれない。 (@qryxip)
v0.2.0
- @tanakh氏製の、競プロ用標準入出力ライブラリ。 (@qryxip)
- 今のRust Analyzerならproconioの補完も十分にできるため、相対的な重要性は下がっている気はする。 (@qryxip)
v1.0.1
-
fixedbitsetやbitset-fixedと比べてGitHubのStarが多く、機能も充実している。(@falrnd)
-
fixedbitsetを置き換えるものではないと思う。bitvecは
Vec<bool>
のように振る舞い、fixedbitsetはBTreeSet<usize>
のように振る舞う。(@qryxip) -
bool
のスライスやVec
のように振る舞う型を提供する。 (@qryxip)整数をビット列として挿入することもできる。
use bitvec::prelude::*; let mut bits = bitvec![u8, Msb0;]; bits.extend(0b00010101u8.view_bits::<Lsb0>()); bits.push(true); assert_eq!( bits.into_iter().map(u8::from).collect::<Vec<_>>(), [1, 0, 1, 0, 1, 0, 0, 0, 1], ); // ^^^^^^^^^^^^^^^^^^^^^^ ^ // 0b00010101 true
v0.5.7
-
Pythonの
collections.Counter
のようなものを提供する。 (@qryxip)use counter::Counter; let mut counts = Counter::<_>::new(); counts += *b"abbccc"; counts[&b'd'] += 4; assert_eq!(counts[&b'a'], 1); assert_eq!(counts[&b'b'], 2); assert_eq!(counts[&b'c'], 3); assert_eq!(counts[&b'd'], 4); assert_eq!( counts.most_common_ordered(), [(b'd', 4), (b'c', 3), (b'b', 2), (b'a', 1)], );
use counter::Counter; let counts1 = b"abc".iter().copied().collect::<Counter<_>>(); let counts2 = b"cde".iter().copied().collect::<Counter<_>>(); assert_eq!( (counts1.clone() + counts2.clone()).into_map(), [(b'a', 1), (b'b', 1), (b'c', 2), (b'd', 1), (b'e', 1)].into(), ); assert_eq!( (counts1 - counts2).into_map(), [(b'a', 1), (b'b', 1)].into(), );
-
2020年の時は
__getitem__
/__setitem__
にあたる操作ができない、それほど有名ではないという2つの理由で提案から外したが、前者は私が実装し、後者についてはいつの間にかめちゃくちゃ使われるようになっていた。 (@qryxip)
v0.1.11
-
C++の
std::unordered_multiset
にあたるものを提供する。 (@qryxip)use hashbag::HashBag; let mut bag = HashBag::new(); bag.insert(b'a'); bag.insert(b'b'); bag.insert(b'b');
-
BTreeMap<T, usize>
などで頑張ることもできるが、結構手間であるためコンテスト後によく悲鳴が聞こえた記憶がある。 (@qryxip)
v4.2.1
-
グラフ関係のアルゴリズムを提供する。 (@qryxip)
petgraphと比べてAPIが簡略化されており、こちらであればアルゴリズムコンテストでの利用に耐えるのではないか。
#[rustfmt::skip] let maze = [ b"...##", b".#...", b".#.##", b".#.##", b".#...", ]; let h = maze.len(); let w = maze[0].len(); let (path, cost) = pathfinding::directed::dijkstra::dijkstra::<(usize, usize), _, _, _, _>( &(0, 0), |&(i, j)| { [ (i.wrapping_sub(1), j), (i + 1, j), (i, j.wrapping_sub(1)), (i, j + 1), ] .into_iter() .filter(|&(i, j)| i < h && j < w && maze[i][j] == b'.') .map(|p| (p, 1)) }, |&p| p == (h - 1, w - 1), ) .unwrap(); assert_eq!( path, [ (0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (4, 3), (4, 4), ], ); assert_eq!(path.len() - 1, cost);
v2.2.0
-
Rustでは自己再帰するクロージャを書くのに一手間要るが、その一手間をやってくれる。 (@qryxip)
use proconio::input; use recur_fn::RecurFn as _; input! { f0: u32, f1: u32, n: [u32], } let fib = recur_fn::recur_fn(|fib, n| match n { 0 => f0, 1 => f1, n => fib(n - 2) + fib(n - 1), }); let fib = |n| fib.call(n); for n in n { println!("{}", fib(n)); }
-
上記の例を書いているときに気付いたが、rust-analyzerがハングしてしまう。 (@qryxip)
v0.4.1
-
[T]
への境界チェックを先に行うことで、「特定の[T]
にチェック無しで何度でもアクセスできる添字型/範囲型」を作れる。 (@qryxip)[T]
からは[0, n-1]の範囲のindexing::Range
が取れ、そこから「より小さな」indexing::{Index, Range}
が取れる。そこから境界チェック無しのアクセスが何度でもできる。let mut xs = vec![0, 1, 2, 3, 4]; indexing::scope(&mut xs, |xs| { let range = xs.range(); // 境界チェックをスキップしてアクセス for &x in &xs[range] { println!("{x}"); } // 空ではないことをチェック let range = range.nonempty().unwrap(); // そうすると「最初の要素」と「最後の要素」に境界チェック無しでアクセスできる println!("{}", xs[range.first()]); println!("{}", xs[range.last()]); });
// これはコンパイルエラーになる fn f(xs: &[i32], ys: &[i32]) { indexing::scope(xs, |xs| { indexing::scope(ys, |ys| { let index_of_xs = xs.vet(0).unwrap(); let _ = ys[index_of_xs]; }); }); }
-
上記のrecur-fnもそうだが、原理がわかってしまえば手作りできる類のものではある。 (@qryxip)
v0.1.3
-
[T]
/Vec<T>
の添字をusize
以外にできるライブラリ。 (@qryxip)use index_vec::{index_vec, IndexVec}; index_vec::define_index_type! { pub struct Idx = u8; } let items: IndexVec<Idx, u8> = index_vec![b'a', b'b', b'c']; let mut i = Idx::new(0); i += 1usize; assert_eq!(items[i], b'b');
-
冷静に考えるとアルゴリズムコンテストには使いにくい。私の提案だが、freezeするからといって入れるべきではなかったかもしれない。 (@qryxip)
v0.1.3
-
参照の継続(名前がわからない)を簡易にする。 (@qryxip)
次のようなことをやりたいとき
with_modulus
はネストする必要があり、視認性が悪い。use proconio::input; fn main() { input! { m1: u32, m2: u32, m3: u32, } with_modulus(m1, |m1| { with_modulus(m2, |m2| { with_modulus(m3, |m3| { let x = m1.mk(0); let y = m2.mk(0); let z = m3.mk(0); }); }); }); } fn with_modulus<F, O>(modulus: u32, f: F) -> O where F: for<'modulus> FnOnce(&'modulus DynamicModulus) -> O, { f(&DynamicModulus(modulus)) } struct DynamicModulus(u32); impl DynamicModulus { fn mk(&self, value: u32) -> DynamicModInt<'_> { DynamicModInt { value: value % self.0, modulus: &self.0, } } } struct DynamicModInt<'modulus> { value: u32, modulus: &'modulus u32, }
そこでこのライブラリを使えばフラットにできる。また
with_modulus
の定義も簡単にできる。use with_locals::with; #[with] fn main() { input! { m1: u32, m2: u32, m3: u32, } #[with] let m1 = modulus(m1); #[with] let m2 = modulus(m2); #[with] let m3 = modulus(m3); let x = m1.mk(0); let y = m2.mk(0); let z = m3.mk(0); } #[with('local)] fn modulus(modulus: u32) -> &'local DynamicModulus { &DynamicModulus(modulus) }
また上記で紹介したindexingに(無理矢理)使うこともできる。
fn f(xs: &[i32], ys: &[i32], zs: &[i32]) { indexing::scope(xs, |xs| { indexing::scope(ys, |ys| { indexing::scope(zs, |zs| { todo!(); }) }) }) }
↓
use with_locals::with; #[with] fn f(xs: &[i32], ys: &[i32], zs: &[i32]) { use indexing::scope as with_indexing; #[with] let xs = indexing(xs); #[with] let ys = indexing(ys); #[with] let zs = indexing(zs); todo!(); }
-
多分使い所は限られる。 (@qryxip)
-
私の提案だが、こっちも早まったかもしれない。 (@qryxip)
v3.14.2
-
手書きで書くにはだるいが、ライブラリとして持つほどでも無いようなショートハンドを多数提供する。 (@qryxip)
maplit風のマクロや、
i1024
型やu7
型とかもある。use std::collections::BTreeMap; use amplify::{ bmap, num::{i1024, u7}, s, }; let _: String = s!("foo"); let _: BTreeMap<i32, i32> = bmap!(0 => 1); let _ = u7::try_from(42).unwrap(); let _ = i1024::from(1) << 1000;
v0.15.5
-
「自己参照」をする構造体を、健全性(soundness)を保ったまま定義する機能を提供する。 (@qryxip)
ライブラリの設計をやらかしたときに、利用側でリカバリする用途に使える。
use std::mem; use ouroboros::self_referencing; let mut stack = ResettableStack::from([0, 1, 2, 3, 4]); assert_eq!(*stack.borrow_remaining(), [0, 1, 2, 3, 4]); assert_eq!(stack.pop(), Some(4)); assert_eq!(*stack.borrow_remaining(), [0, 1, 2, 3]); stack.reset(); assert_eq!(*stack.borrow_remaining(), [0, 1, 2, 3, 4]); #[self_referencing] struct ResettableStack { buf: Vec<i32>, #[borrows(buf)] remaining: &'this [i32], } impl ResettableStack { fn pop(&mut self) -> Option<i32> { self.with_remaining_mut(|remaining| { let popped = remaining.last().copied(); *remaining = &remaining[..remaining.len() - 1]; popped }) } fn reset(&mut self) { *self = mem::replace(self, [].into()).into_heads().buf.into() } } impl<B: Into<Vec<i32>>> From<B> for ResettableStack { fn from(buf: B) -> Self { ResettableStackBuilder { buf: buf.into(), remaining_builder: |buf| buf, } .build() } }
-
私の提案だが、こっちも早まったかもしれない。 (@qryxip)
v1.0.1
-
extension trait patternのショートハンドを提供する。 (@qryxip)
use easy_ext::ext; use proconio::input; input! { n: usize, } n.times(|| println!("Yes")); #[ext] impl usize { fn times(self, mut f: impl FnMut()) { for _ in 0..self { f(); } } }
-
あまり利用機会は無さそうな上、数行分省略できる程度ではある。 (@qryxip)
-
私の提案だが、こっちも早まったかもしれない。 (@qryxip)
v0.9.0
v0.1.1
v1.4.0
- A string type that is not required to be valid UTF-8.
v1.2.1
- Casts and checked casts
v0.1.2
- Glidesort sorting algorithm
- Pattern-defeating quicksort (pdqsort) (pdqsortをもとにした実装は、 Rust 1.20.0 以降の sort_unstable、 Go 1.19 など) の作者によって、 2023-02 の FOSDEM'23 にて発表された、 安定な比較ソート(stable comparison sort)の実装。 (@mizar)
v1.0.1
- Generic extensions for tapping values in Rust
v0.1.0
- swap values between possibly-overlapping references
v0.2.1 → v0.4.0
- num-bigint v0.2.6 -> v0.4.3
- num-complex v0.2.4 -> v0.4.3
- num-integer v0.1.42 -> v0.1.45
- num-iter v0.1.40 -> v0.1.43
- num-rational v0.2.4 -> v0.4.1
- num-traits v0.2.11 -> v0.2.15
- なんだかんだでみんな使っていた印象。(@qryxip)
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.13.0 → v0.15.6
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.20.0 → v0.32.1
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.2.1 → v0.2.6
v0.7.3 → v0.8.5
- getrandom v0.1.14 → v0.2.8
- rand_chacha v0.2.2 → v0.3.1
- rand_core v0.5.1 → v0.6.4
- rand_hc v0.2.0 → v0.3.1
- rand_pcg v0.2.1 → v0.3.1
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.2.2 → 0.4.3
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.5.0 → v0.6.2
- 色々機能が追加されたと思うが未調査。(@qryxip)
v1.3.2 → v1.9.2
v1.3.6 → v1.7.1
v1.4.0 → v1.4.0
v1.0.2 → v3.4.0
- 色々機能が追加されたと思うが未調査。(@qryxip)
v1.0.0 → v1.1.0
- 個人的には使い道が見出せなかったが、そこそこ使われていた印象。(@qryxip)
v0.2.4 → v0.2.4
v1.0.0 → v1.0.0
v0.9.0 → v0.10.5
- 使い道は多分結構多い。使っていた人も多いのではないか。(@qryxip)
- 色々機能が追加されたと思うが未調査。(@qryxip)
v0.1.3 → v0.1.3
- 使っていた人はいるのか。(@qryxip)
v1.0.2 → v1.0.2
- 今のRustだと
HashSet::from([1, 2, 3])
のように書けるとはいえ、maplitの書き方に慣れている人も多いのではないか。(@qryxip)
v1.5.3 → v1.8.1
- itertoolsがこれを返すことがあるので、それで使っていた人もいるのではないか。(@qryxip)
v14.3.0 → v15.1.0
- なんか遅いらしいし、実用していた人はいるのか。(@qryxip)
v0.2.0 → v0.4.2
- まあまあ手軽に使えたはずだし、使っていた人もいたかも。(@qryxip)
v0.1.0 → v0.1.0
v0.3.6 → v0.4.3
- RustでAtCoderに参加している人にとっては、言わずと知れたライブラリ。 (@qryxip)
- v0.3からの変更として致命的なバグの修正と、APIの追加がある(後で書く)。 (@qryxip)
v0.1.8 → v0.1.12
-
The MIT non-military non-spy Licenseというライセンスだったのが純粋な
MIT OR Apache-2.0
に変わった。 (@qryxip) - その他の変更点は特に無いはず。
read!
時にstdoutをflushするようになったことくらい?(text_ioでやるべきことか?という気もする) (@qryxip)
v0.5.0 → v0.5.0 削除
- つい最近気付いたが、ライセンスは
MIT
といいつつThe MIT non-military non-spy License。罠でしょこれは (@qryxip)
v1.1.0 → v1.1.0
v1.2.0 → v1.10.0
目次
- AtCoder Rust Uncyclo
- AtCoder言語アップデート (2019年7月)
- AtCoder言語アップデート (2023年1月)
- AtCoder言語アップデート (2024年11月)