日記

Rust Book (Second Edition) 続き

Rust Book Second Edition を読み終えたので、練習がてら AtCoder で数問解いて遊んでいました。

  • 10章(Generic Types, Traits, and Lifetimes): 内容はタイトルの通り。ジェネリクスとトレイトは C++ とか Java を知ってれば難なく理解できる。ライフタイムは Rust 独自の機能という感じで理解するのが難しい。というか実はまだあまりちゃんと理解できていないような気もする。
  • 11章(Testing): テストは #[test] とか assert! とかを使ってそれっぽく書く。rust標準のツールチェーンである cargo にテスト用の機能が予め備わってるのは良い。単体テストは書くソースファイルに書いて tests ディレクトリ以下には結合テストしか置いてはダメというのがしっくり来なかった。自分が python のスタイルに慣れているせいかもしれないが。
  • 12章(An I/O Project: Building a Command Line Program): 簡単な grep もどきを作ろうというシンプルなプロジェクトで、コードを具体的に書いていって、それをどのようにリファクタリングして整理するとよいかといったことが書かれている。とてもわかり易くて良い。
  • 13章(Functional Language Features in Rust): クロージャーとかの説明。最初の節のコード例はあまり良くない気がする(関数をクロージャーに置き換えてるけど、それだけだと何がしたいのか謎)。
  • 14章(More about Cargo and Crates.io): Cargo について。あまり大したことは書いていない。プロジェクト内でも cargo new でサブプロジェクトみたいなものを作れるので、大規模なプロジェクトになってくると便利そう。
  • 15章(Smart Pointers): 難しくてあまりちゃんと理解できていない。Box と Rc をどう使い分けるかあまり良くわかってない。あと RefCell が出てきたあたりで頭が動かなくなった。
  • 16章(Fearless Concurrency): スレッドを立てる話。スレッドと通信方法にはチャンネルを介してメッセージを送る方法と mutex を使う方法の2つがある。
  • 17章(Is Rust an Object-Oriented Programming Language?): オブジェクト指向らしい機能についての話。State パターンはあまりちゃんと知らなかったので勉強になったけど、やろうとしていること(要件自体は小さい)に対して重実装すぎないかと思わなくもなかった。trait はただのインターフェースの要件を書いたものに過ぎないのかと思いきや、trait object なるものを作れたり、trait のメソッドにデフォルトの実装を記述できたりして、思ったより色々できる。C++ でいう基底クラスと大差ない感じ?。あと、最後のほうで Post::new() を呼び出したときに Post 型ではなく別の型の変数を返すような実装方法が書かれていて、色々紛らわしくなるだけで微妙じゃないかと思ったのだけど rust だとそういうのも推薦されているのだろうか…?
  • 18章(Patterns Match the Structure of Values): パターンマッチはとても便利。while let を使ってキューが空になるまで pop し続ける処理が綺麗に書く例が面白かった。
  • 19章(Advanced Features): 細かい話が多そうだったのであまりちゃんと読んでない。
  • 20章(Final Project: Building a Multithreaded Web Server): マルチスレッドの簡単な http サーバーを作ろうというプロジェクト。例題として面白い。最後の方で rust がまだ開発途上にあることを示唆する内容があったのは正直で良いとは思ったけど、直し方が特殊すぎて意味不明なのでなんとかして欲しい。

次に実際にコードを書きたくなったので練習がてら AtCoder の問題を何問解きました。解くものはどれでも良かったので適当に ARC 069 を選びました。以下はそのときのコード。 競プロでは標準入力を受け付ける必要があるのでスキャナーに相当するクラスを tubo28 さんの qiita の記事を参考にしつつでっち上げています。

最後の問題だけは強連結成分分解などをする必要があって実装がちょっと面倒でした。以下は感想です。競プロ程度の用途ならあまり困ることもなさそうな印象です。

  • 型推論がかなり強力なので、let で変数を宣言する時に型を省略して書けることがかなり多くて便利。デフォルトで変数が const なのも良い。
  • 変数のシャドーイングやパターンマッチのおかげでコードを簡潔に書ける。
  • コンパイルエラーに遭遇して原因がよく分からなくてもコンパイラのヒントに従ったり、適当に色々試してると意外と直せる。
  • 書いてて楽しい。
  • やはり開発中の言語なこともあって新機能はガンガン入るので、例えば BTreeSet の range (C++ でいう std::set の lower_bound みたいなもの) は半年前とかなり最近なので、オンラインジャッジでは使えないことがある。

競プロは満足したので次は中規模くらいのコードを書いてなんか遊んでみたいところ。

「情報幾何学の基礎」の輪読

2.3節まで読みました。多様体における接ベクトルの定義が巧妙で面白いしそれがちゃんとベクトル空間を成しているのもよくできているなぁと思った。

その他

  • 和文論文の JAIST Repository: 落下型パズルゲームの定石形配置法とぷよぷよへの適用 を読んだ。ぷよぷよみたいなゲームでは大連鎖を起こすために長期的な計画を立てる必要があって難しそうなのだが、どういう手法が取られているのかふと気になったので調べているとこの論文に当たった。手法としては単純で、(i). 8連鎖程度のパターンのデータベースを手で20種類くらい作っておいて、(ii). 盤面の評価関数を、2駒間の一致関係がデータベースのそれとどれくらい合うかを元にして作り、(iii) 実際に手を選ぶ時には3手くらいまで先読みして、ヒューリスティックで枝刈りしつつ評価値が高くなるものを選ぶ といったことを行う。実験によると、この手法で8連鎖程度ができる火種を構成した後に既存の探索手法に切り替えてさらに火種が大きくなるような工夫を入れたところ、平均で11連鎖程度できるアルゴリズムが出来上がったとのこと。
  • この手法をモンテカルロ探索系の手法を用いるものに拡張する試みもあったようだが、計算時間が膨らみすぎて満足のいくものにはならなかった模様。