/ 最近 .rdf 追記 設定 本棚

脳log[2022-11-12~]



2022年11月12日 (土) [AtCoder] 今日は大和証券プログラミングコンテスト2022 Autumn (AtCoder Beginner Contest 277) があった。コンテスト成績証自分のすべての提出。ここひと月ほど ARC の開催が途絶えていて、そうするとレートが安定するんだなあ。今回は E 問題でも緑 diff 止まりだった一方、F、G 問題がともに橙 diff だったらしい。F 問題はてっきり自分が苦手なタイプの水 diff だと思っていたので意外。■G 問題「Random Walk to Millionaire」の方が見込みがあると思って考えている。とりあえずサンプルが合うところまではできたのだけど、これは O(KKM) であり K,M≦3000 の制約下では時間オーバー。報酬がレベルの2乗だというところが嫌らしいと思うんだよね。2乗でなければレベルの和と個数を覚えておくだけで良さそうなところが2乗だからまとめることができないでいる。レベルごとに独立して遷移を行うせいで K(移動回数)×K(レベル数)×M(辺の数) の計算が必要になってる。■F 問題「Sorting a Matrix」も考えてる。行のソートと列のソートをそれぞれでがんばれば解ける気がするんだけど、「がんばる」が曲者。行のソートは比較的問題が少なくて、列の統計情報を一度記録しておけば素直に比較ができる。列のソート。行ごとに非ゼロの列を選んでソートして列の序列を作り、マージして1本のソート列にする。入力がすべて非ゼロだった場合、最初のソートに O(HWlogW) かかるのと、扱う2項関係が 行×(行内の2項関係) = HW(W+1)/2 個存在するのがつらい。最大ケースで数十秒かかる。あと制約も曲者で、H と W のそれぞれは上限を持っていない。ものすごく縦長の行列もものすごく横長の行列も考えられる。ソート部分の logW がほぼ logHW だったとしても問題はないけど、2項関係の W(W+1) は非常によろしくない。ソート列をソート列として保持したままうまくマージする方法は。それ以前の問題として、エラーなしでは最初の提出 #36477837 (WA×12 / TLE×5) が一番 WA と TLE の数が少ないこともある。愚直にやったものの TLE が一番少ないところと、愚直なのに WA があるところが問題。ケアレスミスなのか根本の方針が答えにたどり着けないものなのか。ダメケースを1つ2つ見つけては結果が改善してるのを確認してるのに提出すると WA 数が何も変わらないのつらい。列のソート(比較)の肝は一方または両方が 0 の行では順序づけを保留することと、同値の場合はグループ化することだというのが今の理解。■@2022-11-14 G 問題。ヒントを見ました。「G は i 回目の移動で頂点 u にレベル X で来る確率が p だとすると、知りたいのはすべての i と C_u=1 なる u について pX^2 の和。(i,u) を状態として \sum pX^2 を管理しようとすると、レベルアップの処理が \sum pX^2\rightarrow\sum p(X+1)^2=\sum pX^2+2\sum pX+\sum p となる。よって \sum p\sum pX\sum pX^2 を管理しておけば更新も含めて計算できる。」 これがヒントであって答えでないのは、これを読んでさえさっぱり遷移が書けなかったから。何度も何度もガチャガチャやって考えてガチャガチャやって考えてお風呂に入って考えた。提出 #36502350 (TLE×13)。書けなかったのは 29 行目と 30 行目と 32 行目。それで苦労の結果が TLE。計算してみたら N,M,K≦3000 で Ds.size=3 で E.sum(&:size)=2×M で C0.size+C1.size=N だからループの回数が K×(3×2×M+N) = 6300 万。Ruby は 1000 万回を超えたあたりから厳しくなってくるのでこのままでは無理だよ。


2022年11月10日 (木) 体験版をプレイしただけだと思っていたオーディンスフィアの製品版(PS2)を持っていたことがわかったので 15 年ぶりに再度始めて今度こそクリアを目指している。しかしやっぱりアクションが厳しいなあ。慣性があるでしょ、自動で滑空して空中の的になるでしょ、攻撃への対抗手段が距離を取るか防御か飛び越えるかでしょ、敵のモーションを見てからじゃ対処が間に合わないんよ。事前に距離を取っていても巨体の頭に引っかかってはじき飛ばされるし、いっぱい湧いてくる特定の敵に触れると凍結して動かない的だし、アイテムは現地調達が基本で備えができないし、被弾しても時間をかけてもスコアが下がって報酬が減るし。時間を制限するなら全体を概観する手がかりを与えてくれないとペース配分も何もなくノーダメージを狙うのもままならなくてただただ忙しいだけ。クリアしたくなるハードルとしてのゲームの枠組みの作り方が下手だと思う。声と絵の良さでまあまあ楽しくやってるけどレイヴスラシルではいっぱい改善されてるんだろうなあ。なんでオーディンスフィアかっていうと「十三機兵防衛圏クリアした!」から。


2022年11月09日 (水) 精進。東京工業大学プログラミングコンテスト2022 の先頭から5問。難易度順に並んでるらしいですよ。コンテストトップ画面がすごく懐かしくもうざい感じで、画像ではなかったので思わずソースを覗いてしまった。IE が咲かせた HTML の徒花マーキータグさんじゃないですか(お仲間にブリンクタグがあるがこれは MSIE の仕業ではない)。クリックすると方向が切り替わる無駄ギミックもサイコー。サイコーにうざい。■A 問題「Next TTPC 2」。差を取って GCD の約数。提出 #36331477 (AC / 209 Byte / 100 ms)。■B 問題「Magical Wallet」。一番単純な形の DP。所持ディジットをキーにして購入数を記録する。遷移にあまり時間をかけないようにする。提出 #36331824 (AC / 382 Byte / 1243 ms)。Ruby で 326 ms の提出(#36329646)があるのでまだまだ。■C 問題「Five Med Sum」。慣れないと5重のシグマ記号は意味不明だけど、これは5つの数列から作れるあらゆる組み合わせの5つ組を考えて足すという意味。「あらゆる」と「足す」だけ認識していれば十分。ある数列のある要素に注目したとき、他2本の数列に小さい要素がいくつあるか、残り2本の数列に大きい要素がいくつあるかがわかれば、現在の要素が中央値として選ばれる場合の数がわかる。提出 #36332261 (AC / 504 Byte / 1918 ms)。制限時間ぎりぎり。同じ値を持つ要素の扱いに困ってしまったけど、実は気にする必要がない。むしろ気にせず便宜上の大小関係があるものとしたほうが重複して数えてしまわずに済む。提出 #36339767 (AC / 513 Byte / 608 ms)。かなり速くなった。このときの実践「ループ展開した文字列を eval するもの。そんなテクニック初めて見たよ! 横目でちらちら見ながらまねしてみたけど、なんでか同等の速度は出なかった。繊細なのね。」 この提出 #36350174 の 18 行目の式が賢い。自分の提出の sumf 変数をこの式にしたい。最初の提出の時点で考えなかったことはないけど、全然まとまらないねってそのときは思った。HI/LO を入れ替えた2つの和を左からと右からでまとめてるっぽい?■D 問題「XOR Tree Path」。最初はビット列を掛け合わせて寄せていく解法(名前がわからん)かと思ったけどだんだん木 DP が見えてきた。葉ノードから寄せて上げていく。記録するのは、反転操作を親に伝播させるときに部分木がいくつの黒ノードを含むかと、そうでないときにいくつの黒ノードを含むか。木 DP の肝は子ノードのマージ部分だけど、ここに罠があった。子ノードが1つしかないときに「反転操作を親に伝播させるときに部分木がいくつの黒ノードを含むか」という数字を反転しない場合の数字に反映させる方法はない。反転操作を打ち消し合う他の子ノードが存在しないから。提出 #36339752 (AC / 602 Byte / 286 ms)。■E 問題「Name Value」。制約が、特に A,B 文字列の長さがやばすぎるだろうと思ったけど、クエリ文字列のスキャンが前方/後方から貪欲に行えるので、それを効率的にやるために準備を頑張ればいい。文字種×(A,B 文字列の長さ) = 2000 万要素くらいの遷移表を用意して許されるのか考えたよね。うーん、ありかなあ。でも1要素ずつスクリプトでコピーするとダメかも。提出 #36341147 (AC / 509 Byte / 1309 ms)。許された。最初は遷移表に添字を記録していたけど、遷移先の遷移表を持たせるのがより直接的ではないかと気がついてそのようにした。人間が脳みそに余計なステップを持っているとコンピュータにも無駄な回り道をさせがち。こういう無駄を詰める思考はコードゴルフと通じている。提出 #36348178 (AC / 392 Byte / 1216 ms)。Array#dup メソッドの呼び出しを省いた(20201207)のと遷移表のサイズを半分にしたのと無駄な Array#min を省いたのと添字を記録していたなごりの無駄な変数を省いた。遷移表のサイズを半減した引き替えに整数の引き算がループの中に4回出現している。メモリ大量確保&コピーとちょっとした整数演算ではどちらが時間を食うかという判断。平均的に速くなったけど重いケースではそれほど変わらず。1度に1要素しか更新しない遷移表を毎回丸々コピーするのがもったいないんだよなあ。空間がではなく時間が。でもたぶんそれをやめると探索が必要になって log が付くのでは? インチキみたいなうまい方法があればなあ。遷移表の行と列を入れ替えるみたいな方法はたぶんうまくないんだよなあ。2要素の遷移表……。■F 問題からは解けません。■G 問題「Count Arithmetic Progression」を考えてる。傾きに注目するにしても直線の切片に注目するにしても 10 の 12 乗以下という制約がネックになって部分点しか得られない(答えが違えば部分点ももらえないが)。注目するなら 30 万以下の要素しかない L,R 整数列になるのかなあ。それで解く方法が見えないけども。@2022-11-11 部分点をもらいました>提出 #36390042。部分点の制約でも青 diff は下らないと思うなあ。探索できる要素ってある? 1ずつ計算せずに済むような単純な比例関係があったりする? どっちも(見つから)ないんだよなあ。DL,DU 変数を賢いデータ構造で仮想化して妥当な計算量で求められるとしたらどう? DU,DL 変数は傾きの上限下限だから傾きを制約する数字が連続的に変化していったら結局 10 の 12 乗に比例したステップが生じると思う。まとめてひと束で計算できる状態の単位が見えない。数列の要素数に比例したステップしか生じなかったりする? じゃあ傾き制約の変化点を順に知る方法は。■@2022-11-16 解説を読んだ。Convex Hull Trick の名前を知った。「Convex Hull Trickを知っていますか?僕は知っています。 - Qiita」「傾きの単調性が要らない Convex Hull Trick - kazuma8128’s blog」 読んだ。直線をソートして順番に交点を求めて上限/下限の変化が知れるらしい。蟻本で既出だったことも知った(初版 286 ページ K-Anonymous Sequence)。しかし書けない。


2022年11月07日 (月) [AtCoder] 精進。先週末の ABC276-G「Count Sequences」(黄 diff)。当日は愚直解さえ作れなかった。今日また考えてみたところ当初の方針だった DP/メモ化再帰とは違って組み合わせで解けそうだった。こう考える。0 から M の値の範囲に N 項の数列がある。両方の制約から各項は前項から最低 1 は増加していなければいけないので、+1 操作を N-1 個の項間に挿入する。値域が M 以下に制限されているので追加で可能な +1 操作は M-N+1 回。これを上限として追加で何も操作しなくても構わない。追加で考えられる操作は、N-1 個の項間それぞれに最大で1回だけ +1 操作を挿入することと、+3 操作を N-1 か所のどこにでも何回でも挿入すること(もちろんプラスの合計が M を超えない範囲で)。+1 操作の選び方と +3 操作の選び方はコンビネーション一発の定数時間で求まる。そうして値域としてある幅を持った数列の種類数が求まる。それが M-5 の幅だった場合、たとえば 0=a1<...<an=M-55=a1<...<an=M など、初項 a1 が取り得る値が 0 から 5 の 6 通り考えられるのでこれを掛ける。困ったのは、+3 操作の上限を決めて 0 個、1 個、2 個と挿入する場合の数の合計も、+1 操作の上限を決めて 0 個、1 個、2 個と挿入する場合の数の合計も事前に累積和を計算しておくことで定数時間で求められるのだけど、初項が取り得る値のバリエーションを累積和に掛ける方法がわからなかった。たとえばメインループで +3 操作の回数を決め打ったとする。追加で可能な +1 操作回数の上限がわかるので累積和を引く。しかし +1 操作回数が 0 回のときに初項が取り得る値の種類数と 1 回のときに取り得る種類数は異なる。+1 操作の選び方に階段状の倍率を掛けたものの累積和が欲しい。倍率はスライド式であり、×5,×4,×3 かもしれないし、×3,×2,×1 かもしれない。あるいは初項の前へのプラス操作が他と統一的に数えられたら。困ったときはお風呂で考える。普通の平坦な累積和と階段状の累積和を組み合わせればいける。いけなかったのは、N,M の制約上限が普段より厳しい 10 メガなのであり、コンビネーションの事前計算に加え累積和を2本も作成する 3N の処理で制限時間の4秒を超えてしまったこと。10 秒まで実行されるコードテストで 4.4 秒からなかなか縮まなかった。■提出 #36313584 (AC / 773 Byte / 3938 ms)。C1 メソッドの値から A 数列を作成するときに呼び出し回数を半分に節約したり、メソッドの中身をインライン展開したり、メインループの共通項を ICI として括り出したり、fn 数列の前部を切り捨てて添字のオフセット計算を省略したり、いじましい努力の結晶ですよ。Ruby によるすべての提出を見ると、tinsep19 さんの提出は最悪ケースこそほぼ同じタイムだけど、内訳を見ると1秒早かったり倍早かったりするものが多い。4秒ぎりぎりの最悪ケースの位置が異なってるのが面白い。向こうの最悪ケース(1つだけ)はこちらの最悪ケース(13 個)ではないのだ。■メインループを逆順にすると必要なのが累積和の末項だけになって事前の作成が不要になる気がするなあ。■提出 #36318378 (AC / 736 Byte / 3061 ms)。メインループを逆順にして累積和が配列2本から変数2個になった。*smallN* ケースだけやけに遅くて最適化の余地があるみたいだけど、それ以外は概ね良好かな。汚いという意味では良くないけど。■「スナネコ「ABC276Gの解説に追記しました」 https://t.co/9pw10g1SOS https://t.co/bRGlSd8RcW」。異次元からの眺め。さっぱりすぎる。


2022年11月05日 (土) [AtCoder] 今日は ABC276 があった。コンテスト成績証自分のすべての提出。AC までの所要時間は A=2分、B=3分、C=16分、D=5分、E=16分、F=32分。青パフォで Highest 更新でいい日だなーと思ってたんだけど、E、F がそれぞれ緑 diff、水 diff だったと知って AtCoder の参加者に畏れをなしている。結局あれだ、簡単に解ける問題を(やや)早く解いただけ。実際考えるところは F 問題までなかったし、F 問題も実装しながら考えを固めていった感じ。■A 問題「Rightmost」。サンプルに助けられた。String#index で書いていたところを String#rindex に修正。■B 問題「Adjacency List」。教育的問題。グラフ問題で辺の集合を受け取って頂点本位の隣接頂点リストを作成する練習。■C 問題「Previous Permutation」。100 要素の順列を全探索はできない。入力から(じか)に直前の順列を作成したい。サンプルを眺めるだけでも手の付け所はすぐにわかると思う。辞書順で後ろにあるものは必ずどこかで隣接2要素の大小関係が初期状態から逆転して降順になっている。それを1段階解消したものが直前の順列。最も後ろの逆転が最も辞書順に与える影響が小さいので解消すべきはそれ。あとはサンプルを見ながら実装をがんばる。けっこう面倒くさかった。これは今の思いつきだけど、普通の数って組み合わせの数じゃない、それを順列の数に変換する手順があれば、K-1 にその手順を適用するだけで答えになりそうだけど、そういう手順はないのかな。10 進数を 2 進数に変換するみたいな手順。……。できそうだけど K がべらぼうな大きさになるからうまみがない。■D 問題「Divide by 2 or 3」。できる操作は素因数から2と3を取り除くだけ。とりあえず全部の2と3を取り除いてから全体が一致するかを比較したり、不必要に取り除きすぎた2と3の分の操作回数を補正したりするのもありだけど、全体の GCD を予め求めて A 数列から取り除いておくのがやりやすいかな。■E 問題「Round Trip」。グリッド問題は制約を一番に見る。一瞬、行と列のそれぞれが1メガだからすべてのマス目をなぞることができないのかと思ったけど、行と列を掛けたマス目の合計が1メガに収まるという制約だった。どうやって環状のパスを見つけるか。スタート地点の上下左右をスタート地点にして(ややこしい!) BFS で陣取りをしていって、異なる陣地がぶつかったときに Yes かなと思った。スタート地点の上下左右からどれかをスタート地点にその他をゴールにして BFS なり DFS をするのもありかな、とは終了後に考えた(※元のスタート地点を経由する長さ2のパスを抜かりなく除外すること)。グリッド問題をグラフに見立てて辺を陽に持つのは原っぱのようなグリッドのときに厳しいかな。大は小を兼ねるというけどサブクラスに固有の最適化を手放す余裕が Ruby にあるかどうか。■F 問題「Double Chance」。制約が 20 万なので累積的に求めていかなければ時間が足りない。カードが1枚ずつ増えていくときにそのカードの寄与を考える。最初は答えそのもの(期待値)を更新していこうとしたが、これはうまくなかった。K 枚での期待値と K+1 枚での期待値では分母が異なるので、直前の分母を掛けて今回の分母で割って、など面倒くさい。すべてのパターンの max(x,y) を合計したものを累積的に更新するのが良い。K=1 なら 1 通りを合計したもの、K=2 なら 4 通りを合計したものを記憶する。K が k から k+1 に増えるときは (k+1)*(k+1)-k*k = 2*k+1 通りの max(x,y) を加算する。更新しながら利用できる累積和が必要なので BIT の出番。BIT は(配列を使った累積和と比較すると)取得が対数時間になってしまうけど更新も対数時間で済むのが嬉しい。■G 問題「Count Sequences」(黄 diff)。とっつきは悪くないと思ったんだけど、愚直解も作れないのでは論外。


2022年11月04日 (金) AtCoder Type Checker「ds14050 さんのスコアは 0.06 です。中間的なタイプです。/ds14050 さんの内部レート: 1438.00/計算に使用したコンテスト数: 182/ds14050 さんの平均順位率: 0.4461/内部レートによる補正値: 0.4455 (ds14050 さんと同程度の内部レートの人が取得している、平均的な平均順位率)」■得点が同じ人同士で比べたときに 100 人中 44 位くらいの位置(早さ)にいるらしい。その位置というのが自分と同レートの人の平均とほぼ同じなので、「中間的なタイプです」。Ruby を使っていてソースが短い(タイプ数が少ない)ことを勘案すると、考えるのもタイプするのもかなり遅い部類なのでは? 言語ブーストがあってやっと中間。再度「俺の脳みそのクロック周波数は常人の3分の1だ!


2022年11月03日 (木) [AtCoder] 精進。ARC004-C「平均値太郎の憂鬱」(青 diff)。以前に埋めようとしたときは B 問題までしか埋められなかった。この問題の鍵は N の範囲をどこに限定できるかということに尽きる。以前はそれが不十分だった。今日は上と下の両方を抑えることができた。こう (1+2+...+N-1)/N <= X/Y = (1+2+...+N-M)/N < (1+2+...+N)/N) 以前はそもそも上と下の両方を抑えようという意識が働かなかったと記憶している。雰囲気で片方を抑えてそれで?って感じ。ぼんやりしてら。■しかし罠が2つ。提出 #36180781 (WA×8)。考えられるすべての N と M を N の昇順に出力することが求められていたのに1組しか出力していなかった。提出 #36180916 (WA×5)。分子と分母にまったくどうでもいい数が共通に掛けられているケースに対処できていなかった。「ただし、入力は既約分数とは限らない」とはそういう意味。約分している場合もそのままの場合もあるというだけではなく、無駄に数字をふくらませている場合があった。■提出 #36181139 (AC)。テストケースがあればデバッグが捗っただろうけど、古い ARC のは公開されていない。


2022年11月02日 (水) 6年2組のマグカップにひびが入っていた。底から側面に筋が見える。大きさと形がちょうど良くて愛用していただけに残念だ。割れた陶器って研ぎ立ての刃物と同じくらい、つまり普段使ってる包丁よりずっと良く切れるからね(経験者語る)、中身をぶちまけたくもないし、今後は置物にするのがいいだろうなあ。■ちょうどいい大きさと形っていうのは、大きいところと、しゃれたところのない素直な形だってところ。よくある 330 mL (の8分目)では飲みたい一杯分より少ないし、口の広さも底の小ささも容量と安定を損なう。キャンバスとしての用を求めたマグカップが並の商品より完璧に実用的だった。■計ったらすりきりで 500 mL のものを8分目から9分目で使用していたらしい。このサイズ全然ないよね。■計量カップを使用した回数に比例して誤差が蓄積する。3回で計ると 500 mL だけど2回で計ると 400 mL とちょっとだった。普段の1杯は 400 mL ちょっとの8分目で 320 mL とちょっとというのを最終結論にしたい。■次に使うのは「となりのトトロ スペシャルコレクション マグカップ(たんぽぽ編)」。かわいいものが好きです。実物のサイズ感は不明だけど 400 mL 弱はまあまあ満足できる容量だと思う。サーモスの真空断熱マグが容量と形の面から最適で、さらに付加価値(断熱)まであって最初に目を付けたんだけど、ステンレス製は飲み口に不安がある。複合素材にしたらしたでそれ相応の面倒があるし、蓋なしの保温性は限定的。さらに電子レンジが使えないときた。もう何年も電子レンジがない生活だけどいつまでもないとは限らない。この用途には陶磁器が無難かなと。(サーモスのケータイマグはせんユニットやパッキンを交換しながらもう4年使ってるよ! 買い物バッグもレジ袋有料化前からサーモスの保冷バッグだよ! (謎フォロー))■届いた。肉薄(※肉厚の反対でニクウスのつもりで書いたけどこれはニクハクと読むらしく意味が違う。ここではニクアツノハンタイと読んでくれ)なので横から見るとコンパクトだけど上から内容積を見比べるとそれほど遜色がない。計るとスペック通り 400 mL 弱と強の違いがあって、その差 30-50 mL。これまで使っていたのよりおよそ 10 % 少ない。事前の予想通り「まあまあ満足できる容量」だと思う。


2022年10月31日 (月) [AtCoder] 精進。先週末あった ABC275-F「Erase Subarrays」(ぎりぎり青 diff)。本番中は区間 DP なのかなとか左右からの DP なのかなとか実は一方からの DP でいけるのではとか考えるもまとまらなかった。直前の要素から連続するのかそうでないのかでコスト計算が変わってくるんだけど、それをうまく扱えなかった。■AtCoder に関連して流れてきたツイートを読んだ。こちら「難しい問題だが、独力で解けた。連続部分列の DP は直前の要素を使用しているかをフラグとして持ってあげるとよいことが分かった。また、配列内の足し算は注意が必要(今更感のある知見だが。。。) 提出 #36113489 - AtCoder Beginner Contest 275 https://t.co/4ka1Ik7YoZ」 「直前の要素から連続するのかそうでないのかでコスト計算が変わってくる」ことがわかっていても「直前の要素を使用しているかをフラグとして持ってあげるとよい」と明示されることが問題解決のヒントになるのだなあ。■提出 #36122711 (TLE×4 / 2191 ms) のち 提出 #36123362 (AC / 1864 ms / 107396 KB)。Ruby によるすべての提出を見ると他の2つの AC 提出と比べてメモリ使用量が5倍以上ある。なんか違うことをやってんだろか。■提出 #36124108 (AC / 1452 ms / 45264 KB)。メモリ使用量の差は Hash か Array かの違いだと思ってまねしてみたけど、時間もメモリもなんか違う。それに AC 提出の片方のメモリ使用量を1桁読み間違っていたこともわかった。18 メガじゃなくて 180 メガだから自分のと大差なかった。だいたい同じことをやってるよ。


2022年10月28日 (金) [B! security] フォーム入力支援やサイト最適化サービスの改ざんについてまとめてみた - piyolog」■ブコメで「サブリソース完全性」について知った。関連>20220520。だけどこれ活用が難しいよね。ハッシュ値が提示されていなくて検証できません、というケースがほとんどだろうから。もちろん正しくやりたいところが正しくやる手段が用意されているのはいいことだけど、閲覧者の視点から正しさや完全性を求めると、やっぱりアクセス先とは異なるドメインから来るリソースは基本的に拒否することになる。それができるのは偏屈な人間だけだから、あいだをとって、検証できない外部リソースは基本的に拒絶されますよ、という世界が訪れることがあるだろうか。あと別のブコメが、スクリプトが読み込むスクリプトが改ざんされたら integrity 属性も役に立たないだろうと書いている。まあ、そうだよね。それだけの自由と信用を Web ページは埋め込む外部スクリプトに付与しているということだ。というか形式から言っても連帯責任のごとく一体のものと見なすのが妥当だと思うので、外部スクリプトが仮になにか悪さや粗相をしたらすべての責任がまず Web ページをサーブした者に生じると考えていいのでは。これは理想世界での事後の話。現実世界で事前にできることは。無責任の連鎖に巻き込まれたくないので自分はスクリプトを許可しないわけです。それで壊れるサイトには近寄らないのです。いつでもそうできるといいね!■■■「オリジン間リソース共有 (CORS) - HTTP | MDN」を読んだ。いくつかシナリオがあるっぽい。一番単純なケースでは、リソースをホストしているサーバーが Access-Control-Allow-Origin ヘッダを使うことで外部からの使用可否をコントロールできるっぽい。しかし、しかしだね、そもそもの目的がリソースただ乗りの制御にあるのではなくて、同一オリジンへのリクエストだけを許されたスクリプトに抜け穴を提供するために用意されたように見える。ブラウザは img タグなどを含むすべての外部リソースについて Access-Control-Allow-Origin を確認しているのだろうか。Web はいつの間にかそのようなものになっていたのだろうか。もちろん違うはずで、抜け道に対して「オリジン間 HTTP リクエストのリスクの緩和に役立てています」とはどういう皮肉か。■きっかけはこのツイートだったんだけど、「@chokudai AtCoder の API に Access-Control-Allow-Origin など CORS 指定がないのにはなにか理由があるのでしょうか? これがあれば、有志ウェブサイトが AtCoder の API を叩くためだけに Heroku などに依存する必要がなく、GitHub Pages などでの静的ホスティングが可能になると思うんですが…」、Heroku を利用することで何がどう可能になるのかがまだわかっていない。難しいね。Heroku の無料プランがなくなるんだっけ? そうすると有志ウェブサイトは何ができる?


2022年10月22日 (土) [AtCoder] 精進1。今日あったキーエンスプログラミングコンテスト2022(AtCoder Beginner Contest 274)-F「Fishing」(黄 diff)。解答の方針はすぐにわかった。幅 A の区間で魚を捕るときに中途半端な範囲を選ぶ理由がないので、ある魚が x にいるタイミングで x+A までの範囲で魚を捕る。ある魚と他の魚の関係は、(初期位置の前後)×(速度差)=(追いつく、追いつかれる、逃げられる、逃げ切る)の4通り。魚ごとにタイムラインを再生して区間内にいる他の魚を管理する。■提出 #35895537 (WA×8)。時間内の提出はこれ。WA の原因は3つ(!)あって、1つは 21 行目 t = (A+dx).fdiv dv。これは「追いつく」関係のときに追い越してしまって幅 A の区間から出てしまうタイミングを計算する式。正しくは t = dx.fdiv dv。2つめは 11 行目と 19 行目 でハッシュのキーに 0 を使っているところ。0 と 0.0 をソートしたら結果が不定になった(Ruby 2.7 の場合)。それではハッシュを入る方と出る方の2つに分けた甲斐がない。実数で閉区間は扱いにくいんよ(どうして区間を x+A 未満にしてくれなかったのか)。キーが 0 であれ 0.0 であれ入る方を必ず先に加算しなければいけないのにできていなかった。3つめは「追いつかれる」ケースの処理を忘れていたこと。■提出 #35903826 (AC / 712 Byte / 2942 ms)。これだけミスがあって時間もかかるなら解けた喜びしかない。なんにも惜しくない。■■■精進2。同じ ABC174-E 問題「Booster」(水 diff)。時間中は F 問題にかかりきりで読まなかった。ブースターを使う使わないを総当たりしてダイクストラ法かなと考えたりもしたけど、どうにもはまらない。むしろ巡回セールスマン問題(TSP)だった。■提出 #35902406 (AC / 674 Byte / 1847 ms)。これまで2問くらい TSP(roblem) を解いてるけど久しぶりすぎて忘れていた。ワーシャルフロイド法と同じ見た目をしていることを思い出すのに時間がかかり、何とか書き上げても TLE を2回食らった。以前にタイムを詰めに詰めてこれが決定版と言えるものを作ったんだけど、内容を覚えていないしどの問題かも思い出せなかった(そのときに競ってアイデアを提供してくれたアカウントは覚えている。精進中に見かけた名前を最近またコンテストで見るのは嬉しいものだけど、逆もあって寂しい)。唯一思い出したのが 12 行目の 1,0 = (N+M).times.partition{|b| 0<vs[b] }。これで TLE が解消した。


2022年10月20日 (木) [Ruby] 以前に max_of メソッドの不在について書いたけど(20210715)、もうひとつ、ことあるごとにリファレンスを探してみてはないなあとがっかりするメソッドが Bignum#flip (Integer#flip)。Bignum って性質としては数値より文字列に近いはずで、だからインスタンスを無駄に大量に保持したり使い捨てにしたりするのが MLE (メモリ使用量過多) や TLE (実行時間過多) の原因になると考えている。いきおい1つのインスタンスを大事に使い回しする使い方になるんだけど、だけど、インスタンスへの作用のさせ方が big |= 1<<k とか big ^= 1<<k になる。|=^==|^ を使ったシンタックスシュガーだとしたらそれも残念だけど(でもそうだよね?)、1 ビットに作用させるためだけに Bignum の一時インスタンスを作成して、桁数に比例したビット演算をさせているのが(たぶん)、もったいなくて仕方がない。リファレンスを漁るけど flip メソッドが見つからない。bitset みたいな特別な道具としてではなく普通の整数で多倍長のビット演算ができるところが、速度で不利になりがちな Ruby が強みにできるところであるので、機会を逃さず Bignum を酷使していきたいと思っている。これは昨日の日記(20221019)への言及。


2022年10月19日 (水) [AtCoder] 精進。先週末にあった ABC273-F「Hammer 2」(黄 diff)。当日は終了直後にプライオリティキューを使った愚直シミュレーション解を投げて TLE を食らっていた>提出 #35695089 (TLE×28/AC×74)。実は TLE の背後に WA が隠れている。今日はもうちょっと手をかけて効率的にシミュレーションをするようにしたところ AC が出た。■提出 #35789620 (AC / 1898 Byte / 63 ms)。方針はこう。スタート地点から左右2手に分かれて駒を進めていく。右へ進んだ駒が壁にぶつかったら、その壁に合うハンマーを手に入れるのにどれだけ移動する必要があったかを左に進んだ駒に尋ねる。ハンマーにぶつかったら、逆に左に進んだ駒に教えるために現在の移動距離(+原点に戻るまでの距離)を保存する。左右どちらの駒もそれ以上進めなくなるまで交互に進めていく。工夫のしどころは壁の並びに合わせてハンマーに序列をつけることと、序列順に並べたハンマーの揃い具合をキーにして移動距離を保存したところ。揃い具合というのはビットフラグそのままではなくて、手前から何番目の壁まで漏れなく対応するハンマーが揃っているか。事前準備もいろいろやった。まず、ゴール(X)より後ろにある壁と対応するハンマーはないものとする。壁と対応するハンマーがスタート地点から見て同じ側にあって、ハンマーの方が手前にあるときもないものとして良い。ゴールより手前にある壁であって、対応するハンマーがその壁の向こうにあるものがあれば到達不可(-1)。このような事前準備をする意味は、壁もしくはハンマーにぶつかったとき、それは必ず反対側に進んだ駒に関わるものだという状況を作ることにある。一部例外はあって、ゴールと反対側にある絶対に通れない壁(とその向こうにあるハンマー)は判断を保留して残したけども。これが嘘解法だったらもう知らない。計算量のオーダーが狂っていて非常にありそうではあるけれど。左右への移動回数の合計が N 以下で、その中にあるループで書き込む移動距離の総数も N 以下。でも Bignum の桁数が N 以下だから結局 O(N^2) になるのかな。■「アライグマ「F問題は区間DPなのだ! DP[L][R][f]=いままでにいったことのある左端がLで右端がRでいま(f?右端:左端)にいるときの移動距離の最小値 とすればいいのだ!」」 わからないのだ! F 問題あたりにあって DP っぽいけど解けないなーって問題がだいたい区間 DP だと最近気がついたのだ。■自分の解法の O(N) の部分を上手くやる方法がないかなあ、ないかもなあとちらちら考えている。それというのは、ランダムなビットを立てていく、だけど決まった順番で立てていくときに、そのときどきで最も右にある 0 のビットの位置を知る方法。今は N 桁(≦1500)のビット演算でやっている。これをやる LIS のような、あるいは BIT を使った上手いやり方がないものかなあ、と。ビット演算で上手くやる類の問題だということがショートカットの不在を暗示しているような気がしている。……。いやいや、普通に右端の 0 の位置を覚えておいてその 0 が埋まるたびに次の 0 を探すようにすればループ全体で長さ N をなぞるだけになる。■提出 #35802156 (AC / 1813 Byte / 63 ms)。元が Bignum の定数倍の良さに助けられてほとんどインタープリタ起動のオーバーヘッドのみの時間だったので、63 ms から良くはなっていないけど、O(N^2) から O(N) になったのではないかと思う。あとは嘘解法でなければ。■解説放送「パナソニックグループプログラミングコンテスト2022(AtCoder Beginner Contest 273) - YouTube」で 区間 DP から先の考察をやっていた! 壁すら取っ払って必須の(折り返ししなければいけない)ハンマーを左右交互に取るところまで突き詰めていた! それを前提にしてさらに先へ行こうとしていた! でもこういうのって聞かされても理解できはしないんだよなあ。■提出 #35802759 (AC / 1819 Byte / 62 ms)。String#index メソッドに第2引数を渡し忘れるミスで O(N^2) になっていた。今度こそ本当に O(N) のはず。タイムも間違いなく誤差だけど 1 ms 縮んでいる。■あ、事前準備でソートが避けられないから O(NlogN) にはなるのか。解説放送(まだ見てる途中)でも O(N) だとは言ってなかったしな。