ロアちゃんかわいい

競プロっぽい話がなされる駄文の掃きだめ

WSLでWin-Kexを使う場合の日本語入力(uim+mozc)

Win-Kexを使う時に日本語入力が上手くできず、結構長いこと詰まっていたのが解決したので、解決方法を書いておきます。

前提

  1. WSLでWin-Kex(Kali LinuxのデスクトップGUIをWSL上で使う仕組み)を使っている
  2. Win-Kexで日本語表示までは行えている

2については他の記事を参照してください。

概要

IM(Input Method)のうち、日本語入力に成功したのは uim + mozc の組み合わせのみです。 そのため本記事でもuim+mozcの手順を書きます。

大まかな手順は次の通りです。

  1. uim + mozc のインストール
  2. input method を uim に設定する
  3. uim の設定
  4. Win-Kex用の環境変数を設定する
  5. 起動時にツールバーを表示する設定(任意)
  6. 再起動

1. uim + mozc のインストール

sudo apt install uim uim-mozc mozc-server mozc-utils-gui

2. input method を uim に設定する

他のがあったら消した方がいいかもしれません。

im-config -n uim

3. uim の設定

kaliのホームボタン(?)を押してuimと検索すると、input method(入力メソッド)というのが出てくるのでこれを押します。

全体設定。

mozcの設定。

mozc keybindingの設定。ここはお好みで適当なキーを設定してください。

適宜設定したら保存。

4. Win-Kex用の環境変数を設定する

通常のLinuxでは /etc/environment などに設定すればよいのですが、 Win-Kexは VNCセッションを使って起動されるためか、これらの設定が読み込まれません。

そのため Win-Kexの起動スクリプトに直接設定します。

/usr/lib/win-kex/xstartup

に以下を追記してください。

export GTK_IM_MODULE=uim
export QT_IM_MODULE=uim
export XMODIFIERS=@im=uim

5. 起動時にツールバーを表示する設定(任意)

ツールバーはなくても動くのですが、現在どちらのモードなのかわかる方がいいと思うので、ツールバーを出したい人は設定してください。

「設定マネージャー」から「セッションと起動」を開きます。

ここの「自動開始アプリケーション」の箇所に以下のように追加してください。

名前: uim-toolbar コマンド:/usr/bin/uim-toolbar-gtk3

6. 再起動

Windows側で

wsl --shutdown

をして落としてください。

おわり

あとはブラウザなどで動くことを確認してみてください。 上手くいくとこんな感じ↓で表示されます。

AIを使ったSnowPro Core Certification対策

概要

仕事でSnowflake使うから研修と資格受けてね~と言われ、SnowPro Core Certificationという資格を取りました。
AnkiとChatGPTをフル活用したので状況と方法を載せておきます。

ただ、実際に自分で色々使ってみるのが一番なので、この対策はあくまで電車の中の暇つぶし程度にして、自分でSnowflakeを使ってみてください。無料枠で使えばそこそこ色々試せます。

SnowPro Core Certification対策の難しさ

試験は基本的に4択クイズなんですが、結構細かい仕様まで聞かれます。
出題範囲は公式ドキュメントになっています。
対策本などは出ていません。問題も非公開なので、所謂「傾向と対策」が出来ません。

探せば過去問に近い練習問題が3000円ぐらいでネットに出回ってるんですが、ぼくはそもそもこういうベンダー資格みたいなのがマッチポンプ感あって好きじゃないです。なのに追加でお金を払うとかいやすぎ!
と言うわけでお金がかからない方法を模索しました。

(そして状況的に試験までひと月もなかったので、なるべく時間のかからない、定期試験対策的な方法を探す必要がありました)

ChatGPT

出題範囲が公式ドキュメントである以上、公式ドキュメントを読み込むしかないんですが、こんなもん全部丸暗記できるわけもありません。
というわけで、ChatGPTに公式ドキュメントを読み込んでもらい、練習問題を出題してもらうことにしました。

Snowflakeのドキュメントは大きく分けて6つに分類され、それぞれから出題されます。
流石に問題量的に一気に生成させることはできないので、チャットを各分野に分けて出題してもらいました。
出題形式についてですが、Ankiを使うことにしました。

Ankiの活用

時間がない中の対策となると、なるべく報酬系が働きやすい形式がいいです。
というわけでAnkiという電子単語帳を使うことにしました。
Ankiはエビングハウスの忘却曲線に沿って、1度出題した問題の出題間隔を自動調整してくれます。
さらに問題自体もhtmlを使ってカスタマイズできるので、非常に便利です。

実際に投げたプロンプト

章ごとに次のようなプロンプトを投げました。

Snowflakeの認定資格であるSnowCore Proという試験を受ける予定があります。
そこで公式ドキュメントを直接参照するような模擬試験を解きたいと思っています。
公式ドキュメントのユーザーガイドのリンクは以下にあります。

https://docs.snowflake.com/ja/guides

このうち、「(ここに分野名が入る)」分野のドキュメントを一通り読み込み、それを元に(ここに適当な出題比率に合わせた問題数が入る)問程出題してください。

ただし、ドキュメント中の注釈や補足などは優先して出題してください。

問題はAnkiという電子単語帳ソフトで使用するので、次のカラムを含めてください。

問題番号、問題文、選択肢、正解、解説

選択肢ついてはHTMLのul, liタグで囲んで出力してください。A, B, C, Dなど選択肢のアルファベットが付いていると尚良いです。
解説では根拠となるリンクを示し、これもhtmlのタグで囲んで出力してください。

結果、適切な表を出してくれました。表はスプレッドシートに貼り付けて、tsvに変換してAnkiに取り込みました。
根拠付で出してくれるので、リンク先に飛んで確認することもできました。

実際の使用

問題を見る→回答を確認する→ドキュメントに飛ぶ→間違ってればその問題を修正、ドキュメントがなければ自分で探して貼る
のループを繰り返しました。

実際にやってみると回答が完全ではないのと、出題にムラのようなものがあるので、さらにリンクを用意して問題を追加で生成させたりしました。
後は自分で問題集を作っていくとそれはそれで色々頭に入るので、問題作成自体に学習効果があると思います。
ただ、結構な精度で上手くドキュメントを要約して出題してくれるので、自分で1から問題集を作るよりずっと早くできました。
時間がない中の苦肉の策でしたが、ドキュメントを頭に叩き込みたい時は悪くないかもしれません。

後は、Ankiとの相性が良かったです。表を吐くのに慣れているからか、インポートにもそこまで手間がかかりませんでした。
パッと根拠となるドキュメントに飛べるのもいいですね。
表示はこんな感じです↓

カードタイプなんかは適当に編集しました。


今回わかったこと

  • ChatGPTにAnkiの問題を出題させるのは割と相性が良い

- 特にこういう公式ドキュメントを広く読み込んで4択クイズみたいな試験には強い

  • ただし精度は完璧ではないので、ちゃんと根拠となるリンクを吐かせた上で手動確認・修正して問題集の精度を上げていく必要がある

適正出題数について

なんとなくの見積もりですが、全体で少なくとも600問ぐらいは用意した方が良いと思います。多少被ってもいいので。
以下の方法を使うとそこそこ質を保ったまま問題数を担保できると思います。

より効果的な方法について

今回余裕がなかったので手を付けませんでしたが、実際にはより細かい章分けごとにリンクを用意して、リンクごとに数問出題してもらう方が良い問題集が出来上がると思います。
チャットを分けることもできるので、ChatGPTの文字数制限も回避しやすいはずです。
以下の記事が良くまとまっているので、ドキュメントへのリンクを貼り付けて生成させると尚良いと思います。

https://zenn.dev/takotaketako/articles/8af6a1f17cb00e

「すごいHaskell楽しく学ぼう!」メモ

○はじめに
数年ぶりに読書感想文を書く。大雑把なイメージだけ書くのと、既に読んだ人向けの内容になる。

「すごいHaskell楽しく学ぼう!」というHaskell入門の名著があり、それを一通り読んだ。
元々は英語版がインターネットで公開されているらしいが、ぼくは英語がそんなに得意じゃないので、Haskellと英語の両方を同時に勉強することもないと思い邦訳を買うことに。

結論としては、Haskellは面白いので全プログラマがやるべき。

○面白いところ

1. 複雑な計算を簡潔に書ける
あまりにも簡素な関数定義に始まり、リスト内包表記、強力なパターンマッチなど、表現力が高い。
よく繰り返しを再帰でしか書けないみたいな誤解をたまに見かけるが、後述するモナドとdo記法の組み合わせによって手続き的な書き方も十分可能。

全ての関数がカリー化されているのも面白く、このおかげで高階関数を扱いやすくなっている。
例えば
Int->String->Int
という型は、第一引数にInt、第二引数にStringを取り、戻り値がIntであるような関数を表す。
どうしてこのような奇妙な書き方になっているのかと言えば、ここでカリー化の話が出てくる。
Haskellにおいて->という演算子は右結合であり、
Int->String->Intは Int->(String->Int)と等価である。
つまり、「第一引数にInt、第二引数にStringを取り、戻り値がIntであるような関数」と「第一引数にIntを取り、戻り値が引数にStringを取りIntを返す関数であるような関数」が等価になる。
Int->String->Intに一つ目の引数だけ与えるとString->Intの関数が返ってくるので、この関数にあとから二つ目の引数を与えてやることができる。

2. 演算子を自前で作れる
関数だけでなく、中置演算子を簡単に定義できる。もちろん結合順位も。
このおかげで足りない記法があっても自前で何とかできる。

3. モナドが強力
ここが一番難しかったが、一番面白かったのもここ。
モナドは次のような演算を定義してある型クラスmのこと。

>>= :: (m a) -> (a -> m b) -> (m b)

`>>=`はbindとも呼ばれる演算で、モナドというものを特徴づけるものとなっている。

型コンストラクタは値に文脈を付けた計算処理を表しているとも取れる。値aにIOという文脈が付いていると、IO aは入出力の結果aという得られる処理と言うことになる。
モナドでは文脈mを上手く連鎖させていく、つまり文脈自体に上手く文脈同士の演算を書いていけば、それ以外の関数では文脈同士の演算を気にしなくても良いということを表している。
(正確には文脈同士の演算ではないのだけど)

より正確には、
・ある値に文脈を付けたい(のでそういう型クラスmが実装される)
・mに対して文脈付きの値を引数に取れるようにしたい。文脈を外して値だけ取り出し、それに何か関数を適用するという処理は実は結構共通化することができる

という感じ。Rustでもよく層をまたいだエラー処理のためにパターンマッチで値を外しているが、モナドがあればこの辺の手間を省ける気がする。

IOとか扱う時は特に便利で、mがIOだとすると、
1. IO aを実行して中の値aを取り出し、
2. aの値によってIO bを生成する

という具合に、>>=によってIOを次々実行できるようになっている。
さらに、Haskellではモナドのbind連鎖に対してdo記法という糖衣構文が用意されていて、まるで手続き型のように副作用のある部分などを扱える。

○不満な点
1. 副作用が多くなればなるほどHaskellっぽい書き方ができなくなる
当然と言えば当然だが、do記法が大量にあるとやっぱりちょっと微妙な気持ちになる。

2. 低レイヤが記述しづらい
まずメモリを触れない。そして基本的に遅延評価されるのでいつ何が実行されるかがわかりづらい。
一応C言語と連携することでやってる試みはあるっぽい?
もしくはそういう目的ならRustやOCamlを使うのが良いのかもしれない。

3. オブジェクト指向的な書き方ができない
これはそこまで大した問題ではない気もするが、ある変数に対してどういうメソッドが存在するのかを補完できない。
オブジェクト指向のドット記法はそこがシンプルで強力だった。エディタの支援は大事。

○純粋関数型とソフトウェア設計
純粋関数は基本的に単体テストが書きやすい。
ただし必ずしもすべてのテストがしやすいかと言われるとそうではなく、Haskellのように純粋関数を主体とすることで単体テストしやすい部分を増やす圧力がプログラマにかかっているイメージ。
単体テストを増やすと何が良いかと言うと、ブラックボックステストによって壊れにくいテストが書きやすい。
ソフトウェアテストは基本的にどんなパーツであれ、インターフェース部分が仕様を表していることが多く、ここをテストするのが良い方法だとされている。
Haskellでも副作用を持つことはできるが、副作用を持つ部分はテストしづらいので、必然的に副作用を持たない部分を増やし、副作用を持つ部分をギリギリまで避ける方針にするだろう。
そういう圧力がプログラマにかかるという点で、プログラマに良い設計を強制しているともいえる。

○Functor, Applicative Functor, Monadについて
Monadについての嬉しさは上に書いた通り。
Monad以外にも代数的構造としてFunctor、Applicative Functorというのがあるので、Monadと比較しつつ考えたことをまとめておく。

Functorは(a->b)という関数を受け取って(f a->f b)という関数を返す関数fmapが実装されているような型クラスfのこと。
つまり、fがFunctorであればa->bの関数によって、文脈を保ったままf a -> f bという変換を得ることができる。
Functorは「関数によって移せるもの」を表すことができる。
また見方を変えると、f aという値があるとき、a->bという関数があればf bを得ることができるともみられる。この見方を強化すると、Applicative Functorの便利さがわかる。

Applicative Functorはf (a->b) -> f a -> f b、すなわち自身の中にa->bという関数が入っているようなfを受け取ってf a -> f bである関数を返すような関数が実装されている型クラスのこと。
正確にはa -> f aも実装されている必要があるが。

fがApplicative Functorであれば、f aという値があるとき、a->bである関数をfに入れた値を受け取って、f bという値を計算してくれる。

とはいえ、実はMonadの方が強く、ある型がMonadであるなら、FunctorもApplicative Functorであることも満たすので、実際にApplicative Functorとかを使うかは微妙な気がしている。
いずれにせよ、Functor、Applicative Functor、Monadについては、文脈の取り扱い方を定めたもの、という認識をしておいてよさそう。実際には圏論由来らしいけど。

モナドの定義について
最初、モナドの定義が
(>>=) :: m a -> m b -> m b
じゃないのが不思議だった。しかしよくよく考えてみると、

(左辺値) >>= (a->m b) >>= (b -> m c)

のように連鎖させるとき、aの値次第でm bの生成方法を制御する純粋関数を作る方が、m aから値を取り出す処理を入れた関数を作るより簡単で、シンプルになることに気が付いた。
bindの定義で、文脈から値をどう取り出して、どのように右辺値の関数を適用するかを決められるなら、右辺値はより簡単な純粋関数でよいわけだ。
そして、>>=を定めておけば、m a->m b->m bも適切に定まる。

この「文脈」というのが厄介で、例えばIOだったりすると、値を取り出す処理を一々記述するのが大変になるだろう。そしてIOの結果を取り出して次の値に渡すと言うのは共通化されてしかるべきだ。
結果、do記法での記述も非常にシンプルになる。

単に共通化という意味でもそうだが、(a -> m b) という形であれば、制御構文を模倣した関数を記述できるという理由もあったようだ。
https://haskell.jp/blog/posts/2020/io-monad-and-sideeffect.html#io-%E3%83%A2%E3%83%8A%E3%83%89

clippyのくせにぼくのreturn文に口を出すなんて

生意気だぞ‼️

rustでwebアプリを書いていたんですが、ぼくの美しいコードに黄色い波線を付けてくる愚か者⁉️ rustは結構気に入ってるけどぼくの美しくて洗練されたreturnに口を出されるのは困っちゃうんだよ

早速消してやるぜと思って調べたら、Cargo.tomlから設定できずにCLI叩くしかないぜみたいな記事が出てきました。

Rust コーディング環境構築@VSCode

このぼくにシェルスクリプトを書いて初期化しろとでも言うのか⁉️

そんなわけないよね~と思ってダメ元でCargo.tomlに

[lints.clippy]
needless_return = "allow"

を追加してみたら上手く動きました。えら~い!

二度とぼくに逆らうんじゃねえぞ……💢

夢月ロアは早く帰ってきて

面倒なので過去問あまり解かずに基本情報に受かりたい

基本情報技術者試験を受けて多分(?)受かりました。

僕は過去問を周回したりする、いわゆる試験勉強みたいなのが苦手です。
なので僕みたいな怠惰な人が日頃からダラダラ本を読むことで過去問をあまり解かずに受かる方法を残しておこうと思います。

どちらかというと、普段ダラダラ読んでる本の中から試験に役立つ本をリストアップするというのが正しいかもしれません。

目次

自己紹介

都内某所でプログラマとして働いています。
数年前までAtCoderをやっていました。
会社ではAWSのインフラ色々いじったり、PHPの異常レガシーコードをしばいたり、react書いたり、大きめのデータ移行したりと色々やっています。

基本情報技術者試験

IPAが作っている資格試験です。ITに関する色々な内容が試験に出ます。
この資格は独占業務があるわけではないので収入が安定するみたいな利点はありません。しかも受験料は7500円、高すぎ。二郎系ラーメンが7杯も食べられるわ
じゃあなんでそんな資格受けたのかというと、僕は大学の経歴が怪しい人物なので、転職なりを考えた時に最低限の保証をしたくなるからです。

  • 非情報系の人が最低限履歴書に書ける内容が得られる
  • 問われる知識が広く浅いので、勉強した内容の確認にちょうど良い
  • 最近はCBT方式で受験がしやすい、会場さえあれば年中受けられる

試験範囲について

↓に載っています。
www.ipa.go.jp

ただちょっとわかりにくいと思っていたところ、↓のブログを見つけました。
[https://amg-solution.jp/blog/7632https://amg-solution.jp/blog/21947]

非常にわかりやすく出題範囲がまとまっていて、この内容全部頭に叩き込んだら確実に科目Aは解けると思います。とはいえ、僕は受験前にこれを読んでません。早めに知りたかった……
過去問周回しながら↑のブログの内容を頭に叩き込んでいくのも割とありかなと思います。のろのろ本読むんじゃなくて過去問周回がいいぜ!という人はこっちで多分大丈夫。

科目Bは後述する方法で余裕なので、もう受かったも同然ですね。

勉強方法について

科目Bとか、コードを書く知識を問う問題をどうにかするためにAtCoderをしましょう(宣伝)
atcoder.jp

色々な人がデータ構造とアルゴリズムの解説を書いているブログがあるのでおすすめです。
コンテストに出るとめっちゃ楽しいんですが、勉強のためにやる場合はコンテストの成績より内容を重視すべきなので、最初はライブラリをあまり使わずになるべく色々なアルゴリズムを実装するのが良いと思います。
バブルソートナップサック問題動的計画法を頭の中でイメージできるぐらい慣れてくると科目Bは余裕だと思います。

それ以外試験範囲をなんとなく網羅するために何冊かよい本があるのでリストを書きます。
アプリケーション層から徐々に降りていくと楽なイメージ。このリストでカバーしきれない範囲があるので、その辺は↑で紹介したブログを見てもらうのが良い気がします。カバーしなくても6割は余裕だと思います。
後はメタ読みで解ける問題が結構あったので、問題をよく読むようにするとよいと思いました。

  • Webを支える技術:Web概論。RESTとか、HTML以外のXML関連技術辺りは適当に流して良さそう
  • マスタリングTCP/IP入門:IPアドレスからTCP、あとsshとかWAFとか、とにかく大事な知識が色々載っています。めっちゃよい
  • ソフトウェア工学:大勢で行うソフトウェア開発の概観がわかります。広く浅くな本なので、知ってるところは可能な限り読み飛ばすのがよいと思います(

https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%B7%A5%E5%AD%A6-%E5%B2%B8-%E7%9F%A5%E4%BA%8C/dp/4764905094

受験

大体上のような本をだらっと読んでから、過去問を解いてみると午前も午後も8割ぐらい解けました。
最近遊んでばかりいて過去問周回の暇はほとんどなく、3回分ぐらいしか解けませんでした。
下振れて落ちたらいやだなあと思っていましたけど、本番も問題ありませんでした。

科目Aは上述の本を読んでいると安定して8割取れて、科目BはAtCoderで緑になれるぐらいにデータ構造とアルゴリズムを勉強していると余裕な感じでした。
後は文章をちゃんと読むと答えが導出できるようになっていました。

科目Aでもっと点を取りたい場合は、↑のブログ見て企業法務とかマネジメントとか、その辺の対策をするのが良さそう。

おわり!

あまり万人受けの方法ではないですが、たまにこういう人見かけるので、何人かには役立つはず?
応用情報もこのノリで受からないかなあ。受かったらまた何か書こうかと思います。

余談ですが、この記事を書いている時点では厳密には合格ではありません。経済産業大臣が合格を認定するという決まりがあるので、合格点を取っていても来月まで合格が出ないのです。

2022年振り返り

一年振り返りをします

仕事してました😡おわり😡

なんや😡😡😡

仕事

web系の会社に入りました。
真面目にwebのことを勉強したりプログラムを書いたりします。
微妙に規模が大きいベンチャーなので色んな種類の仕事があって楽しいです。
php、js、react、sql、その他色々を若干書けるぐらいになりました。

採用の仕事を頼まれて、逆求人イベントに出向いて学生とお喋りしたりとかもありました。
会社名は公開していないんですが、映像扱うwebシステムに興味があったらお声がけ頂ければ会社の話をするぐらいは出来ると思います。(競プロerの水準で見るとお給料そんなに高くないですが……)

競プロの知識が役に立つことはぶっちゃけなかったですが、一度だけ役に立ちそうなところまで行き、熱い展開でした。
ある不具合の原因になっているプログラムを参照しているファイルを全て列挙する必要があって上司が迷っていたので、「プロジェクトに入っているファイルに深さ優先探索を行って、参照関係を全部辿れば大丈夫です。そういうスクリプトを書きましょうか」と言ったらドン引きされて却下されました。かなしい
(軽度な不具合だったので、結局一部の重要なファイルのみ修正を行って事なきを得ました)

仕事以外

「仕事でやっていると仕事以外でプログラムを書こうという気にならない」という話をTwitterでよく見かけます。
誰がそんな迷信信じるかよ、と思っていたら全く書く気が起きません こまった
AtCoderやる気力も起きず、かと言って何もしないのもあれなので、脆弱性攻撃の勉強とかしていました。C言語にちょっとだけ詳しくなりました。
ネットワークのお勉強もちょっとだけやっていました。マスタリングTCP/IP入門編を読んでいましたが、分かりやすくてよかったです。

夢月ロア

かわいい はやくもどってきて😢

来年

  • 応用情報辺り取っておきたい
  • CTFやってみたい
  • Kaggleやってみたい
  • 競プロもやりたい
  • 数学勉強したい

まとめ

おふとんきもちいい すやすや よいおとしを

典型90問をRustでやっていく その1

おはようございます。

今回はタイトル通り典型90問をやっていきます。
この記事には

  • 前書き
  • 各問題の考察・感想などと、Rustで詰まった部分
  • その他雑談

が含まれます。苦手な方はご注意ください。

前書き

大学で途中から競プロやる余裕がなくなってしまって歯がゆい思いをしていましたが、社会人になったらかえって時間ができたので、復帰がてら解いていきます。
折角なので流行りのRustを覚えつつやっていこうと思います。
「典型90問を解いてみた」系の記事は沢山あるので、今回は「Rustを始めてみたいな~」と思ってる人に多少役立つ内容を目指せればと思います。
と言っても文法とかは自分で調べていただくのがよいと思います。「素人はここで躓きました!」みたいなメモとしてご利用ください。
Rustよくわからんまま書いてるので間違いがあったらごめんなさい。

典型90問 なに

E8さん(https://twitter.com/e869120)という高校生時代からレッドコーダーの凄い人が企画・作題された90問の問題集です。
競技プログラミングで出てくる典型的な要素を詰めた教育コンテンツで、僕ぐらいの層(AtCoder灰~青)にちょうど良いっぽいです。

ご本人が詳しく解説されてるので、こちらをご覧ください。

qiita.com

E8さんは昨年末に本を出されているので、こちらも是非。

Rust なに

Rustはプログラミング言語のひとつです。
特徴として

  • 生成コードの実行速度がC/C++レベルで速い
  • 安全性の高いコードが書きやすい
  • 利用可能な範囲が広い(組み込みからwebまで様々)
  • モダンな文法や機能(これよくわからないまま言ってます みんな言ってるので多分あってます) 

などがあります。
競プロにおける難点としては次が思い当たるので敬遠してました。

  • 慣れるまで書きづらい
  • 入力を受け取るのが面倒
  • コンパイル時に可能な限りエラーを検知するため、いくつか面倒な制約がある
  • エラー処理が面倒
  • ぶっちゃけC++で書く方が楽そう

proconioという素敵なライブラリが用意されたので、入力受け取りが面倒な問題が解決されました。
という訳で今回はその他の難点をこちらでどうにか対処出来ればと考えています。

競技プログラミング なに

この記事見に来てて知らないなんてこと流石にないでござるよ~(笑)

おまえ だれ

ぼく こるぼー(@zero_kpr)
きじにしてき れんらく くれ

夢月ロア だれ

かわいい だいすき
はよもどってきて

環境構築

ではやっていきます。
と言ってもここ長くする気はないので、こんな感じのツールがあって便利だよ~という話だけします。

コンパイラ・ビルドツールなど

rustupというツールに各種ソフトが含まれています。インストールはこちら(https://www.rust-lang.org/ja/tools/install
rustupにはCargoというソフトが入っています。

エディタ

vscodeを使います。ここは別に他のエディタでもあまり変わらないと思います。
拡張機能でrust-analyzerを入れましょう。
rust-analyzerはrustのリンターやコード補完、フォーマッターなどの機能を含む拡張機能です。
余談ですがLSP(Language Server Protocol)というのがあるらしく、そのおかげでrust-analyzerを他のエディタでも使えるみたいです。

後述しますが、なんかrust-analyzerが対応しているバージョンの問題でCargo.tomlファイルのeditionを2018にする必要があります。
そうしないとrust-analyzerがプロジェクトの読み込みに失敗します。
cargo newコマンドで新しいプロジェクトを作るとき、デフォルトだとeditionは2021に設定されているので、cargo.tomlファイルを開いて修正しましょう。2021を2018に書き換えるだけです。
もしくはcargo newを行う時に--editionで指定できるみたいなので、そちらでも良いと思います。

cargo atcoder

プロジェクトの作成や、書いたコードの提出を一括でやってくれます。超便利。
テストケース通らなかったら提出しないという親切設計なので安心です。

詳細はこちら(https://github.com/tanakh/cargo-atcoder)に全部載ってます。

2022年5月14日現在でちょっとした注意点があります。
cargo-atcoderでは内部でcargo newコマンドを呼び出すため、生成されたプロジェクトではeditionが2021になっています。
こちらはバージョン指定とか出来ないので、生成後に直さないとrust-analyzerがプロジェクトを読み込まず、補完などが効きません。

あと、cargo-atcoderのreadmeに書いてあるconfig.tomlの設定は絶対にやる方が良いです。
これをやらないとビルドに毎回時間を取られる上に、無駄な実行ファイルが大量に生成されて容量を食います。

cargo atcoderと、後述するproconioのinputマクロ(の元になったアイデア)はtanakhさんによって用意されたものです。
Twitterのbioに「今すぐフォローすべき競技プログラミング界のスーパーエンジニア」とあるので是非フォローしましょう。
tanakhさんのおかげでRustを始めたと言っても過言ではありません。𝐵𝐼𝐺 𝐿𝑂𝑉𝐸...

夢月ロア

問題が解けなくなったり、変なバグ踏んでイライラした時とかにおすすめです。
ぱっぱやを聴け。
Electronic Dance Roa?【Launchpad】 - YouTube

proconioについて

proconioはrustの競技プログラミング向けのIOライブラリで、inputマクロが主に使われます。
コードの上の方にuse proconio::input;を書いとけばatcoderでも使えます。

rustはそのまま使うと入力がすごく面倒で、予め入力用の関数を用意しておいたりすることになります。面倒!
そこでinputマクロが役立ちます。

input! {
  n: usize,
  a: [i32; N],
}

こんな感じで書くと数値や配列やらをいい感じに受け取ってくれます。超便利!

proconioはstatiolakeさんが、tanakhさんのinputマクロをベースに用意してくださったようです。
元々対応してなかったinteractiveな入力形式にも対応していたり、型推論がちゃんと働いたりとすごいです。
statiolakeさんがいなかったらRustを始めていなかった可能性が高いです。𝐵𝐼𝐺 𝐿𝑂𝑉𝐸...


さて、だいぶ長くなりましたが問題を解いていきます。

001 001 - Yokan Party(★4)

提出したコードは
https://atcoder.jp/contests/typical90/submissions/31498336
です。

これはいつものフッフッフッwですね。
ある値で成立したらそれより大きい値でもずっと成立、みたいなのは二分探索が使えます。

ところで、僕は基本的に二分探索の方法はめぐる式二分探索(https://qiita.com/drken/items/97e37dd6143e33a64c8c)を使うことにしています。わかりやすいのでおすすめです。

Rustでは、変数宣言はこんな感じ↓

let (mut ok, mut ng): (i64, i64) = (0, l);

で構造化束縛みたいなのが出来るようです。便利。

前処理のところは面倒なのでVecのinsertを使いました。この辺はC++にもありますね。

二分探索のところ、C++みたいにtemplateでabs関数をいい感じにしてくれないかと思ったんですが、Rustはそういうのはダメっぽいです。
かわりにi32型にabsがメソッドとして用意されているらしく、

(ok-ng).abs()

で行けました。これならC++とほとんど変わらない文字数で書けますね。
FFの方に教えてもらいました、ありがとうございます。

002 002 - Encyclopedia of Parentheses(★3)

括弧列の問題、苦手。括弧列見ただけで反射的に悲鳴を上げました。

提出コードはこれです。
https://atcoder.jp/contests/typical90/submissions/31505604

定義通りに文字列を作っていき、最終的にVec→HashSet→Vecと変換することで各要素が一つずつになるようにしています。
割と力技で解いてしまったんですが、これは解説のようにbit全探索で解けますね。そちらもこの後に出しました。
この問題は無理な解法で粘ったのもあって結構嵌りました。

Rustでは文字列の結合がString型 + &str型の形式にならないといけないようです。面倒ですね。
次の記事がわかりやすかったです。
Rustの文字列結合はどうしてString+&strなのか - Qiita

あとはイテレータ周りがいまいちわかっていません。

into_iter().collect()

みたいなやつとか。

Rustのfor文はイテレータ専用らしく、vをイテレータに変換し、各要素を見ていくようです。
for x in &vみたいに参照にしておけば借用になってムーブされません。
こちらが詳しくてわかりやすいです。
iter()とinto_iter()の違いとちょっとした落とし穴 - Qiita

こいつfor文みたいな顔をしやがって、裏で生意気なことしてやがるな。

内部でinto_iterを呼んでいるが、into_iterは配列には実装されていない。だからRustではfor文で配列を使えないわけですね。
この辺りはAPG4bを読み終えたばかりだったりすると難しそうです。

for x in &v を回している間はv自体に変更を加えられないので、上のコードでは回りくどいやり方をしています。
この辺りはc++の方が簡単な気がしますが、一方でc++で雑に同じようなことをやるとバグの原因になりがちなので、こちらの方が良いのかもしれません。
もしくはもっといい書き方があるかも?

003 003 - Longest Circular Road(★4)

提出コードは↓です。
https://atcoder.jp/contests/typical90/submissions/31509639

木の直径ですね。二回dfsをします。

Rustではグローバル変数を使うのが色々面倒なので、C++Pythonでやってたみたいに関数からグローバル変数にアクセスするような書き方が出来ません。
もちろん安全性のためですが、一々参照を関数で渡す必要があって、競プロではちょっと面倒です。

とはいえRustにはC++より便利な部分があって、それはタプル型がPython並みに使いやすいことです。
おかげで上のコードのように、dfsの戻り値が綺麗に書けます。

for next_v in &graph[now]になっているところは、先述の借用の文ですね。
この場合next_vも参照になるので、後で参照外しをしています。
for文みたいな顔をして裏で何をしているのかわからないので、ちゃんと何をしてるのかドキュメントで調べる必要があります。いや他の言語でも調べろや。
実際はfor文は3種類しかない(T, &T, mut &T, std::iter - Rust)らしいので、一回理解してしまえばそんなに辛くなさそうです。

004 004 - Cross Sum(★2)

提出したコード↓
https://atcoder.jp/contests/typical90/submissions/31510508

みんな大好き累積和ですね。ここは特に嵌りませんでした。

おわりに

一旦ここで切り上げます。
別の記事に分けるか追記するかはその内決めます。