&:to_i
を _1.to_i
にしたり、2要素の配列を要素に持つ Hash を2つの Hash に分けたり。蓋を開けてみれば 500 ms の余裕をもっての AC だった。■つぎは day1-H「Attack Survival」への提出 #40291192 が 21 ms over で TLE×1 なのをなんとかしたい。たった 21 ms ではあるけど、ジャッジサーバーで慎重に繰り返し実行してそれでも TLE だったということなので、いじって出し直すと逆に悪化したりする。解答の方針を転換する妙案もなく。<<x
と <<y
)が雑だったのと、11 行目の判定が早すぎて 15 行目の前にあるのが良くなかった。たった2要素を得るために 20 万要素の配列を作るのが憚られたので Enumerable#lazy メソッドを初めて使ったよ。■「利用できそうに見えて実は始点と一致しているために有効に利用できない場合に注意して」 嘘だよね。長方形 R に2つきりしかない1差の2点の X 座標(Y 座標)の一方が始点の X 座標(Y 座標)と一致していても±2ずつ移動していけるよね。早とちりで No と答えてる気がするけど、テストケースの甘さに助けられたのか?■まだちょびっとだけ理解が及んでいない部分があるらしい。提出 #40200554 (WA×1)。長方形 R の縦と横の長さを最大限に利用して終点を目指してみたのだけど、1つだけ WA になってしまった。どこに考え漏らしがあるというのか。AC はやはり偶然だったのか。■いいや、大丈夫。完璧だ。提出 #40201186 (AC / 506 Byte / 377 ms)。3行目の SY を SX と間違えていたうっかりミスが 1WA の原因だった。考え漏らしはナシ! 十分に整理して満足のいくスクリプトになった。
勘違いして最初は P-2 を mod にしたのだけど、P-1 にすると具合がいいようだった。」 勘違いしていたというのが勘違いだったみたいで、モジュラ逆数を計算するなら P-2 乗で間違いない。P-2、P-1、P 乗がそれぞれ 1/A、1、A に対応する雰囲気。
.keys
抜けが1つと L[]
抜けが3つだけと実装も素直。根からの距離を BIT で、LCA をダブリングで求めた。根からの距離をセグメント木で管理するなら LCA もセグメント木で求めたらいいと思う。BIT+セグメント木は無駄だし面倒すぎるのでナシ。だってセグメント木は BIT の上位互換でしょ?■提出 #39951562 (TLE×24)。試しにセグメント木で根からの距離の累積和と LCA の両方を管理してみたら派手に TLE だった。累積和は BIT でやる方が軽いのかな。■提出 #39954631 (AC / 3966 ms)。頑張りました。セグメント木にダミーの0番目の要素を入れて添字計算の微調整を省いたり、&:method
形式は Symbol#to_proc
が呼ばれるせいなのか知らないけどやや遅いみたいなのでブロックを渡すようにしたり、せっかくセグメント木で累積和を管理しているのだから根からの距離を求めてから LCA を引き算するのでなく LCA からの距離を直接求めたり、オイラーツアーで作成する配列のサイズが 3N くらいになっていたのを節約して 2N に抑えたり。最初の AC だったなんちゃって HLD よりよっぽど厳しい。■モノイドが乗せられるようにまじめに ST クラスを改良したので、クラスを書く時のマイルールを。まずクラス利用者が知りたいであろう public インターフェイスを書いてから部外秘である private メソッドを並べる。public メソッドの中では、最初に呼ばれるであろうコンストラクタ(イニシャライザ)をまず書いて、つぎにアクセサ(読み取りメソッド)を書く。最後に、なくてもいい存在であり有害にもなり得るので書きたくないミューテータ(内部への働きかけ)を書く。クラスはオブジェクトのテンプレートであり、型通りの処理(不変部分)を書く場所だけど、ではオブジェクトのアイデンティティがどこにあるかというとコンストラクタへの引数でありインスタンス変数(メンバ変数)にふるまいを変える固有の値(可変部分)がある。すべてのメソッドがインスタンス変数に依存するべきだというのはそのため。その依存がないならメソッドの置き場所が間違っているサイン。とかとかいうことを考えながらクラスを書いている。あとはまあ名前だよね。よく言われるように名前重要。ソフトウェアという形のないものにはっきりした輪郭を与えるのは名前。適切な名前さえあればその実体をどう実装するかはどうとでもなるしどうでもいい。好きに、うまくやればいい。コーディング対象として適切な抽象に紛れのない輪郭を与える唯一無二の名前を見出すところが決定的に重要(形容詞増し増しで強調しました)。自分が常々疑問なのは、変数名に型名を使うというひとつの典型パターン(var arr = new Array;
みたいな)。そりゃね、飼ってる猫が1匹だけならその呼び名はネコでも十分わかりますけどね、それは消去法や文脈でそう判断できるというだけであって、直接的な命名ではない。解釈や判断という余計なステップ、疑問や誤解の入り込む余地がある。クラスではなくインスタンスの、それそのものの本質を掴んだ命名をするのだ。■いやでも適切な命名は文脈に依存するということも言えるんだよな。識別子が機能するためには他と区別するのに十分な長さを必要に応じて使うのでいい。1文字変数を使い切ってから2文字3文字変数を使う、みたいな。ハフマン符号的な。その対極がたぶん Java の説明的で長ったらしい命名で、自分は HTML の p タグとか好きでいっぱい使いたくなる人間だからどちらかといえばアンチ Java なんだな。そのくせ、よそ者として文脈を共有しないで他人が書いたコードを眺めてるときに限って「変数名に型名を使ってる」とかを批判的に見てしまうわけだ。勝手な。p X
を答えにしているが、正しくは p X%M
。■終了後の提出 #39648781 (AC)。mod M の世界で A-1 で割りたいけど A-1 の逆元を掛けることができない。どうするか。以前にやってるんだよな。「L 問題だけが解けずに残っていた。余りをとる M が合成数でなければ 9 の逆元が使えて解けるんだけど」。Ruby なので (A-1)*M が 70 ビットになっても気にしないよ。D 問題で時間を使いすぎて 30 分ちょっとしか使えなかったのも悪かったな。■■■D 問題「Tying Rope」。ロープを分岐なしで繋いでいった結果、輪っかがいくつあるかと直線がいくつあるかを答える問題。それだけの問題。■最初の提出 #39629872 (TLE)。40 分かけてこねこねした謎処理が TLE になりました。■2番目の提出 #39631843 (AC)。その後7分ででっちあげた UnionFind が AC でした。どうして当たり前の問題を当たり前に解けないのか。■心当たりはある。道に迷ったとき、とりあえず引き返せばいいものを、前に進んで知っている道に出ようとする子供だった。来た道通った道を2度通るのは退屈なことだ。ABC292-D「Unicyclic Components」、ABC291-E「Find Permutation」、ABC285-D「Change Usernames」というように似たような見た目の問題が続いていたので、似たような解答を書くのには抵抗がある。それで間違えてりゃ世話がないってもんだけど。■提出 #39651186 (AC)。謎処理でも通しておきました。謎っていうか単に左右のノードをたぐるだけなんだけど、だけど、定型から外れた途端に間違えるんだなあ。■■■@2023-03-14 E 問題の問題名って等比数列の意味だったの? 英語名難しすぎる(等比数列・等比級数が幾何~と呼ばれるためには何かエピソードが求められると思う。三角数……と考えてもみたけど、それはむしろ等差数列に近い)。そうすると A-1 で割るっていうのは等比数列の和の公式の分母にある r-1 (あるいは 1-r) のことだよね、たぶん。自分は A 進数で 111...1 で表される数字を 1000...0 から求めるつもりで式を立てたけど、意外な繋がりがあったもんだ(決してぼんやりしているから意外に感じられるのではない)。■■■@2023-03-14 D 問題に関連して Dancing Links という名前を初めて見たと思ったら、全然別のところでも Knuth 先生の名前とセットで見かけたりして。どうして今日一日だけそんなに有名になったのか。夜間に出荷したご注文は翌日発送扱いとなります」との定型文があるけど、これをどう考えればいいのか。■可能性1。発送メールの通りに発送されたあと2時間で届いた。■可能性2。夜間に出荷され注文ステータスの更新を見逃した。発送メール送信は翌朝に繰り延べられた。翌日発送扱いになるはずだけどヤマトがすっごく頑張って翌午前に届いた。■可能性3。発送メール前日(発売日当日)の日中には出荷・配送されていて、発送メール時点では配達拠点に届いていた。注文ステータスと発送メールが嘘。■さあどれだ。あるいは4番目があるか。■あとね、些細に見えて毎回導線の途切れにひっかかってしまうんだけど、出荷メールから注文履歴に飛べない。そこがすべての起点であるのに。1クリックでヤマトのページで荷物の追跡情報が見られないのも地味に残念。どちらに至らない点があるのかはわからないけど。
スマートフォンとケースを1つずつ買うと110ドルになります。スマートフォンの値段はケースの値段より100ドル高いです。ケースの値段はいくらですか?」 110という数字を反射的にキリよく100と10に分けると間違える。こういう問題を 20230203 のときの簡易版職業適性テスト(Gテスト)の検査 C (数理)で見たぞ。残念ながらその手のひっかけは中1のときに散々間違えたあとだ(「100gの水に 5gの NaClを溶かしてできる食塩水の質量パーセント濃度は?」という問いに 5%と答えてしまうおバカな中学一年生でした」)。20230203 のときも実は一度ひっかかったけど逆方向に検算するのが習い性なので(答えを出す前に)訂正できた。以前に「ぶつかってそれではダメだと気がついたら定義に立ち返ってひとつひとつの手順を確かめながらたどるのが方法。ここでは注意が必要だと学習したから立ち止まって確かめることができるというだけで、失敗しないうちや失敗を回避できるようになれば、やっぱり中間を飛躍して答えに飛びつく高速のパターンマッチングの出番だと思う。それが人間の基本で、トライ&エラーで最適化を重ねた結果が思慮や洗練として見えているという気がする」と書いた。2011 年のベストセラーらしい『ファスト&スロー』(ダニエル カーネマン)がすごくおもしろそう。それでね、定型発達であることの不幸は、エラーに遭遇する機会の少なさにあると思うんだ。短絡思考を修正する機会に恵まれていない。■■■@2023-03-11 日本語の話。116 ページから「
20世紀前半の哲学者たちはヒュームの論述を深刻に受け止め、道徳的言説が論理に関するものでも経験的事実に関するものではないとしたら、いったいどういう意味があるのだろうかと悩んだ」。さて、この文は道徳的言説が論理に関するものであると仮定しているだろうか、そしてまた、経験的事実に関するものだと仮定しているだろうか。■「~でも~でもない」の形であれば迷いなく論理に関わるものではないし、経験的事実に関わるものでもないと読み取れる。では実際に見られたように「~でも~ではない」の形はどうだろう。自分は意味を変えずに次のように語を補うことができると考えている。「(たとえ)~で(あって)も~ではない」。そう書いてあるのだろうか。同ページの直前の文がこう「
確かに道徳的言説は、論理的言説とも経験的言説とも区別しなければならない」。論理的言説と経験的言説はそろって道徳的言説と区別されるべきものだと書いてあるのであり、道徳的言説が仮に論理的言説であっても、というのは話の流れに合わない。「~でも~ではない」をどう読み取れば良かったのだろうか。もとはの違いが大違いなのではないか。