IOライブラリの設計
競プロ用の入出力ライブラリ(Rust)を作る
要件
長年抱えてる葛藤が、貼る用のライブラリをゴテゴテに作りこむか、簡潔にとどめたほうが綺麗かという
— しの (@shino_skycrew) October 5, 2020
妥協ラインとして、ライブラリは多少長くしてもよい代わりにすべて main
等の下に追いやります。
- マクロは使わずに、
proconio
のinput!
くらい使いやすいものにしたい - おおよそ 100 ms 単位で最速になってほしい
外部クレートには依存しません。(使えるものなら proconio
を使う…)
完成
使用例
#27339 – Library-Checker(Point Add Range Sum)
下のコードをなんとかかんとかで pack? bundle? したもの。
|
|
とても快適です、ありがとう
純粋に IO の速度を測るなら、Many A + B を使うべきでしょう。
設計
- 初期化時に入力をすべて受け取って
Box::leak
する- ライフタイムであ"~ってなった時、とりあえずこうすると楽になる
- 出力は
std::io::BufWriter
(この 2 つだけでtie
/sync
を切ったcin/cout
やscanf/printf
より既に速い) scan
が返せる型をScan
トレイトで表現し、多相にする- ネストしたタプルや配列も空気を読んでやってくれる
- 整数は
str::parese
の代わりに自力で読む
print
が受け取れる値をPrint
(以下略)- ネストしたタプルも
char
? 知らない子ですね
いまいちな点
- 入力を丸ごと
leak
している- 高々 $10^5$ 程度のオーダーということで…
*mut str
を持っておいて最後にBox::from_raw
すれば drop されるが、IO
は入力の一部を&'static [u8]
として返すのでまずい
- 入力と出力は分離するべきじゃないの?
- 実際互いに完全に独立しているが、別オブジェクトだとめんどくさいだけ
Scan::scan
やPrint::print
が&mut IO
を受け取る必要はないのでは?f: &mut F where F: FnMut() -> &[u8]
とかいちいち書くのも面倒
- インタラクティブは?
src/io_interactive.rs
を作りました。適宜 1 行ずつ読み取るという違いだけの、コピペです(悲しい)- とはいえ一度に使うのは片方だけだし、いいかな…
IO::scan
に、どういうときに型引数を明示的に渡さないといけないのかよくわからない- とりあえず怒られてから直す