/ 最近 .rdf 追記 設定 本棚

脳log[2021-02-08~]



2021年02月08日 (月) [Ruby] while queue.empty?.! というループを見つけて、二度見では理解できなくて三度見直した。見たことのない字面だから nil許容演算子(&.)なのかと最初は思った。ドットノットが出てくるのってすごい。最初に while ! queue.empty? が浮かぶでしょう? そうしたらそこから until queue.empty? へも至るでしょう? 演算子にドットを付けて呼び出そうっていうステップが割り込む余地はないように思う。そういう書き方のパターンを考えたことがなかった。いやまあ自分は最初に until が浮かぶので(「キューが空になるまで繰り返す(until queue.empty?)」)、引き出しのひとつとして蓄えたうえでしまいっぱなしにするんだけど。


2021年02月06日 (土)

最終更新: 2021-05-07T14:21+0900

[AtCoder] AtCoder Beginner Contest 191/C,D,B(空白とスペース)

今日の ABC の C と D はちょっと傾向が違ったよね(E と F は時間切れで読んでいない)。C はむしろ復古的かもしれないけど。

 C 問題 Digital Graffiti

どこに着目すれば数えられるのか、わかりますか? わかりません。

 提出 #19978760 (AC / 969 Byte / 62 ms / 14484 KB)

テキトーに注目して数えて、(÷2では)ダメだとわかって(÷3で)やり直して、31 分かけて鬼の羅列である。

(構造の)理解に頭が必要ないという意味で、これも可読性に優れた読みやすいソースコードの例なんですよ。似たような例にすべての繰り返しを for ループで書くなんてありますね。for さえ解れば鬼に金棒、馬鹿の手にハンマー。目に入るすべては釘。打つべし打つべし。

だけどプログラムは構造化と抽象化を(必要である限り)繰り返して、人間はよりハイレベルな意味を読み取らなければいけないんです。あれをどーしたこーしたなんて作業手順を(人間に向けて)仰々しく並べ立てることに意味はありません。それはソースコードの役割であって、人間に向けたコメントには意味のあることを書いてください。

 「黒に塗られた部分は一つの自己交叉のない多角形となることが保証されます。すなわち、」

これって、黒のマスが1つの塊(ドーナツではない)であって、黒の内部に白のマスが島になっていることがない(逆に黒のマスはたった1つの島になっている)ってことだと読んだ。そのあとで補足的に「白に塗られた任意の 2 マスは、辺を共有するマスへの移動を繰り返し、白に塗られたマスのみを通って互いに到達可能である(マス目の一番外側のマスは全て白に塗られていることに注意してください)」ともあるし、問題文は慎重に 書かれていたと思う。

多角形の解釈についても、色が塗られたグリッドであって座標空間上の点列ではないのだから、書かれていないものを見ようとして見るべき角が見えていなかっただけでしょう。

数学の言葉で書かれた制約の読解に普段苦労するので(20201122p01)、今回の問題文に文句はない。

 「AtCoderの何角形問題についてです https://t.co/kVNwsq8xSC」 / Twitter

すごくいい。そうか、ドット絵師と 3DCGモデラーがいただけなのか。

 D 問題 Circle Lattice Points

図形です。

制約が 10^5 だからどうかなーと思ったけど、普通に数えられる範囲だったみたい。手元ではサンプルに2秒以上かかってたんだけど、ジャッジサーバーは速かった。

 提出 #20002500 (AC / 606 Byte / 833 ms / 14420 KB)

1時間かけて、コンテスト終了1分前の提出。よかった……よかった……。

格子点を数える問題で、入力を小数で受け取るのはやっぱり怖い。小数点以下第4位までって書いてあるので、(文字列のまま) 10000 の下駄をはかせて、ついでに諸々の座標が正の範囲に収まるように平行移動した。負の数が混じると整数除算の丸め方向が期待と異なっていて面倒くさい。

# 0 を足すと答えが変わります。難しすぎるでしょ?

 -1/2 #=> -1
0-1/2 #=> 0

# 1 (イチ)が変数 l (エル)で、中身が正の数だったり負の数だったりすると、もう予測できないでしょ?

上記は Ruby の挙動。仲間はずれらしい>「整数同士の除算演算子の挙動 (C言語、C++、Scala、Java、Rust、Go言語、PHP、JavaScript、Perl、Python、Ruby、Elixir) - Qiita」 Python の整数除算(//)も同じく負の無限大方向に丸められるとか。

他の人の Ruby での提出を見ると、入力を to_r するものが多かった。r は Rational の r. 使ったことがないと使えないし、思いつきもしないのだ。

二分探索の探索範囲をちまちま限定したところで、倍の違いが試行1回の違いにしかならないのだから、2つのループは1つで十分でしたね。これは円を4分割して数えられないか考えていたのが尾を引いている。


競技プログラミングをするフレンズ @kyopro_friends

アライグマ「D問題は、円の中の格子点のx座標としてありえる値の範囲がX-R~X+Rだから、x座標を決めたときの格子点の個数が求められればいいのだ! 誤差が大変だから整数で計算して、負の数の切り上げや切り捨ての計算に気をつけて……、罠がいっぱいあって大変なのだ」https://t.co/6z8erFU3Ym

実は二分探索がいらなかった>画像。三平方の定理! 中学生!

 提出 #20013918 (AC / 265 Byte / 125 ms / 14404 KB)

三平方の定理。速い! 短い!

Integer#sqrt なんてニッチなメソッドを使ってみた。

ところで、やっぱり **2 は遅いみたい。引き算を2回評価することになっても覆らないくらいに。


Ruby での提出を早い順に見てるんだけど、どの人もどの人も平方根をとって計算で格子点の数を求めていた。10行以下のスクリプトで。それが間違いなくすごいんだけど(だって開始後30分ぐらいでの無駄なく短い提出だ)、それらをことごとく撃墜した3つの入力(handmade_marginal_{01|03|05}.txt)が、今回はいい仕事をしていたなと。単に to_f を to_r にしたところで、三羽烏のひとつしか超えられないみたいですよ。

Rational だけでなく BigDecimal の存在も忘れていた。これは「任意の精度で 10 進表現された浮動小数点数を扱えます。」 to_d の d は (big)decimal の d. to_f を to_d にしてもやっぱり3つのうち2つが WA になるようなのは、BigDecimal#sqrt を使わないで Math.sqrt を使っているのが良くないんでしょうか。Math モジュールは、標準とはいえ require が必要な添付ライブラリである BigDecimal を知らないのが普通だと思う。

提出して確かめようとしてわかった。BigDecimal#sqrt を使うとサンプル3で既に TLE が避けられない。

 Ruby で一番最初に AC をとった提出 #19982442 (vmi さん)

入力は Rational で受け取っている。Math.sqrt の結果を検算して条件を満たす限り±1の微調整を施し続けている。そして大事なことは、±1した結果の正当性も確かめている。

単純に±1するだけ、しっぱなし、では、handmade_marginal_{00|04}.txt に捕まってしまうようだ。

書き方を洗練させた結果がたぶんこの提出 #20009989 (kyoshida さん)。find メソッドと count に加算する前の nil チェック。

 二分探索解法だが探索がループごとに1回の提出 #19993857 (n4o847 さん)

左右の点のうち1点が二分探索で見つかりました。左右の点の中間座標は円の中心に由来して明らかです。ではもう1点は? a1 = x*2 - a0

 Integer#sqrt が AC と WA を分けた例

違いは1行だけ。Math.sqrt の結果を(floor ではなく)小数点以下第5位あたりで丸めていたらどちらも AC だったんだろうかダメです

これが Integer.sqrt の実装らしい。

def isqrt(n):
    x, y = n, (n + 1) // 2
    while y < x:
        x, y = y, (y + n // y) // 2
    return x

Math.sqrt とは別に用意する価値があるからこそ存在しているのかな。ニッチとか言ってしまったが、こちらが使い所を知らないだけなのか。

 ABC191 - D - Circle Lattice Points - Senの競技プログラミング備忘録

自分は今回も Sqrt Inequqlity のとき(20200316p01)も、浮動小数点数を単純に嫌ったり怖がったりして難を逃れたけど、こういう風に限界を見極めて対応できるの、かっこいいよなあ。

 空白とスペースについて

B 問題の出力例はスペース区切りだけど、問題文は「A′ の要素を空白区切りで順に出力せよ。」という表現になっている。

ここを参照すれば間違いないという定義があるわけではないけど、空白が white spaces の意味なら、ここに改行もタブも含まれると考えるのが普通(※要注意ワード)。自分は「スペース」(ASCII 0x20)と「空白文字」を使い分けているし、AtCoder にもそのように期待している。

というわけで、わざわざ .join(' ') はしない>提出 #19962733

ダメです handmade_marginal_{00|04}.txt に捕まってしまう。Math.sqrt のアルゴリズムに起因して誤差が蓄積するらしい?


2021年02月04日 (木) [AtCoder] 問題名だけやけに目に入るんだけど、これがそうだろうか>「AtCoder Jumper」 Jamper って書いてる人もいる(複数)。■1000.bit_length==10 でもあるし、二分探索とかパリティでしょって思うんだけど、全然答えにたどりつかない。まずは N が2の冪乗のときからと思うんだけど、さっぱり。このときから何も学んでいないのだ>20170620


2021年02月03日 (水)

最終更新: 2021-05-04T20:49+0900

[AtCoder] AtCoder Beginner Contest 190

先週末の ABC。例によってお風呂で考えるも頭が爆発して無理だと思われた F 問題が、なぜか今日取りかかってみれば解けたので日記にする。

 A 問題 Very Very Primitive Game

すごく難しくて、じっくり 10 分の時間をかけた。

 提出 #19784439 (AC / 119 Byte / 63 ms / 14260 KB)

Aoki と Takahashi の文字列を2回書いているところに余裕のなさが見える。間違えるくらいなら全パターンを網羅して並べればいいんですよ(言っていることが違う>20201101p01.03)。

 B 問題 Magic 3

A 問題より簡単だった。条件を満たすものが1つでもあればいい。Array#any? メソッドの出番です。

 提出 #19786803 (AC / 106 Byte / 68 ms / 14316 KB)

ところで空配列に関して、[].all? は true を返し、[].any? は false を返す。この違いによってメソッドの選択が制限されることがあるかなと一応警戒するんだけど、特にそういう違いは生まれないみたい。むしろそうならないようにデフォルト値が選ばれている。罠があるとしたらそこではなく、穴に落ちるときは all? を選んでも any? を選んでも落ちる。

 C 問題 Bowls and Dishes

制約が K に関して全探索しろと言っている。

 提出 #19795600 (AC / 276 Byte / 1129 ms / 15200 KB)

Ruby で最も速い提出(492 ms)より倍以上遅いんだけど、どういうことなんでしょうね。

本当は今日は F 問題をやるつもりはなくて、この C 問題を速くするつもりで取りかかったのだけど、優先順位をつけた深さ優先探索でやろうとしてうまくいく見通しが立たなかったのだった。

 D 問題 Staircase Sequences

45 分考えた。等差数列の和の公式に2種類あることはこのときに確認済みなので(20201101p01.02.01)、今回は使いやすい方を選ぶことができた。

 提出 #19810009 (AC / 316 Byte / 177 ms / 14400 KB)

珍しく解答の中にコメントがあるのは、書いておかないと脳みそからあふれて何度でも最初から考え直しになるからです。紙と鉛筆を用意すべきなんだよなあ。

 E 問題 Magical Ornament

本番中は残り時間が 30 分しかなかったので問題文が短い F 問題に先に取りかかっていた。同じように考えたかどうかはわからないが、E 問題より F 問題の方が多くの人に解かれていたようだ。自分はどちらも解けなかった。

制約が3重ループを許すと言っている。

解答の後半はもう3回目になるあの形。実行速度にハンデを背負った Ruby でのタイムの詰め方は、このときに研究し尽くした>E 問題 Traveling Salesman among Aerial Cities

 提出 #19823594 (TLE×1 / 2032 ms)

惜しい。とても惜しい。時間制限が2秒なのだけど、実行を打ち切られたときは 22xx ms というタイムになる。32 ms 詰めれば AC になるぞ。

 提出 #19825354 (AC / 656 Byte / 1754 ms / 124536 KB)

ハッシュ表を使っていたところで配列を使ったら余裕の AC。

必然性があってハッシュテーブルを選んでいたわけではなくて、Hash のデフォルトプロックありきでスクリプトを構成していたから、使っていた。TLE は邪道の報い。

 提出 #19825691 (AC / 690 Byte / 1585 ms / 64636 KB)

実は唯一の TLE は最も重いケースではなかった。この提出では TLE だった 21_large.txt のタイムが 135 ms だ。

前半部分で選ばれた魔法石がどうがんばっても連結できないとわかれば、後半の3重ループはスキップできる。そういうこと。

 提出 #19839422 (AC / 834 Byte / 1560 ms / 63468 KB)

前半部分で距離の確定を双方向からやらずに片方向で済ませてみたら、平均的には速くなったけど、一番遅いケースでは 25 ms しか違わなかった。不毛(けがない)

 「研究し尽くした」?

Integer#times を while ループにするだけで 200 ms 縮んでやんの。そんなに違うの? times はイテレータの中では速い方だと思ったけど。

 F 問題 Shift and Inversions

転倒数って固有名詞なのかな。公開された PAST の過去問をやったときに見た>20201111p01。K 問題。それが解いてあった(提出 #18029328)からといって、何かが役に立ったということはない。残念。

最初に、k を増やして数列の初項を最後尾に送り込んだときに、転倒数がどのように増減するかがわかった。わかったからわかったとしかいいようがない。こねくっていたら、転倒数の増減が簡単な計算で求まることがわかった。

それから、転倒数の初期値の求め方を考えた。BIT で殴るのではない、頭のいい方法があるのではないかと考えたが、思いつかなかった。

 提出 #19905237 (AC / 342 Byte / 789 ms / 48888 KB)

BIT です。Ruby や Python で速い提出も同じだったので、転倒数はこう求めるのだ! という頭のいい方法はないのかも。

 提出 #19905970 (AC / 293 Byte / 717 ms / 48844 KB)

実は A 数列をスキャンして作成していた配列 I は不要だった。

BIT を使って転倒数を求める手順も、考え方次第でひと通りではないということ。ソート列を必要とする方法よりは必要ない方法を、BIT へのお伺い(対数時間)が2回になる方法よりは1回で済む方法を選びたい。脳みそはタダだけど計算資源は有限。


2021年02月02日 (火) 八朔 10 kg.


2021年01月27日 (水) 子供が親の監督のもと権利を制限されることがあるように、己の行為の意味が理解できない馬鹿に愚行権は(はな)から想定されないのだなあ。「一方でこの自由の主体たる人物は諸々の能力の成熟している成人であるべきであり、また社会的統制の実行を明確に回避しているわけではないこと、愚行の結果として受ける批判や軽蔑、拒否などは当人が引き受けなければならないことを主張する。


2021年01月26日 (火) 1桁同士の足し算。基本的に雰囲気でわかるようになるんだけど、6+7=13 だけどうにも腑に落ちなくて、6 たす 7 が 13 はないだろう、という感覚に邪魔されて計算が難しかった。そのうち逆張りで、6 たす 7 はイメージじゃないけど 13、という理解が生まれる。通りなれたら迂回路も遠回りとは気づかなくなる、みたいな。


2021年01月23日 (土) [AtCoder] NoSub に関して @evima0 さんのこのツイートがえらいと思う。「現在の AtCoder ではコンテストで一度も提出しなかったら (できなかったら) 不参加扱いですが、問題を読み始めた瞬間に参加扱いにすることを検討しているようです。」■ NoSub 即不正みたいな論調ばかりで想像力の足りない連中に言いたい。NoSub したくてする奴なんざいねーんだよ。いつだって誰だって全完できるなら全完したいしそうするに決まってんだよ。A 問題のサンプルを通す解答すら用意できなかったから NoSub になるんだよ。もちろん戦術的 NoSub の選択肢は知っている。でもそれが?■パフォーマンスの良かった回だけピックアップすることでレイティングが上振れするとしても、その範囲は精々色半分程度ではないか。自分の場合、緑が水色にはなるかもしれない。でも青パフォ黄パフォなんて見たこともないから、粉飾しても青黄の目はない。■にもかかわらず NoSub を含む戦術を駆使してレイティングを良く見せようとする人間は、自分がその程度伸びる未来も描けない終わった人間だと俺は思う。何を気にかける必要がある? そんな他人の足なんざどうでも良かろう。

最終更新: 2021-05-07T14:34+0900

[AtCoder] AtCoder Beginner Contest 189/C,E

今日の ABC。

 C 問題 Mandarin Orange

制約がよく見かける 10^5 ではなくて 10^4 だから雑なやり方でも通る気がしたんだけど、そんな仏心が期待できるはずがなくて、時間が厳しいからこそ制約が緩めてあるのだなあ。Ruby では D 問題よりも解かれてないみたい。

 提出 #19612283 (AC / 190 Byte / 88 ms / 15720 KB)

AtCoder のことを初めて日記に書いた記念すべき日「脳log[20190907p01] AtCoder Beginner Contest 140 E問題」を思い出して書いた。

不安だからそのままにしたけど、今回は更新と更新のあいだに参照が1回だけだから、番兵も1つで足りたと思う(これに対する答え>「実のところ + [N, N]+ [-1, -1] は完全なるコピペ。+ [N]+ [-1] ではダメだったものがどうしてこれで正しい答えにつながるのか、さっぱり理解していない。RU[N]LU[-1] に番兵を1個置くのと2個置くのの違いとは。」)。

 提出 #19649425 (AC / 167 Byte / 68 ms / 15644 KB)

ソートで配列を比較するのが贅沢で余分な時間を使ってるみたいだったのを修正した。88 ms → 68 ms

多重代入部分を読み解く参考に>20201124p01, 20200428p01.08.01

主流の解き方ではデータを蓄えたり捨てたりしながら数列を前から一度だけスキャンするみたい。何を蓄えて何を捨てるんだろう。わからない。ピークの情報は残しておいてもしかたないな。現在の要素をピークとして左側への広がりが知りたいかな。上昇トレンドでは広がりに意味がないな。

 提出 #19675442 (AC / 201 Byte / 69 ms / 15096 KB)

2 WA のち AC。数列を1回通り抜けるだけ。上昇トレンドでインデックスを記録しておいて、下降局面で幅を確定する。

あ、これ8行目の if が常に true でバグってる。

 提出 #19679788 (AC / 199 Byte / 66 ms / 14984 KB)

これが(バグ修正済みの)本当の O(N) 解答。バグといっても等しい要素が多いときに無駄がある、という程度だったみたいだけど。

C 問題でこれをイチから考えるのはあまりに酷だけど、実は O(N^2) が通る制約だったらしい。Ruby で 10 メガや 100 メガが秒未満は無理だと思うけど。

 ヒストグラム中の最大長方形の面積を求める

ここで紹介されている方法が O(N)。自分の(前2つ)はソートしてるから O(NlogN)。

 提出 #19680172 (AC / 297 Byte / 69 ms / 15104 KB)

さっきリンクしたのと同じ日記だけど、「Rubyで一番速いのはこれ。345ms」として参照したのと同じ解法。愚直に検索する O(N^2) 解法の改善案として素直に理解しやすいと思う。

数列がソート済みであればあるほど改善効果がなくなるのではないかな。クイックソートみたい。

 提出 #19700600 (corazon さん / AC)
#ここがよくわからない
#●●●しない限り、次に来る高さと取り出した長方形の最後のインデックスをスタックの中に入れる

わからないのがよくわかる。自分が O(N) 解法を書くにあたって 2 WA した原因がここだから。

要するに、「取り出した長方形」は「次に来る高さ」よりも高い要素なわけだから、次に来る高さの上位互換であるわけ。その「最後の」(=最も左の)インデックスを、次に来る高さの左方への広がりとして記録している。

 E 問題 Rotate and Flip

 提出 #19644038 (TLE×6 / AC×24)

アフィン変換を検索して見よう見まねで書いた。1時間かかった。TLE だった。これ以上はもう余力も時間もなかった。無念。


対称移動のための行列は3つの積ではなく2つの積で表現できるし、それも自分で計算して1つにできる。でもそれだけでは TLE のままだろうな。行列の掛け算をただの配列同士の掛け合わせとして自分で書いてみたりもしたけど、7秒が6秒になるだけだった。


競技プログラミングをするフレンズ @kyopro_friends Jan 23

アライグマ「E問題は、(0,0),(1,0),(0,1)の3点だけシミュレーションすれば全部計算できるのだ!」

な、なんだってー。

汎用的に点を動かそうとするのでなく、具体的に基底を動かすってことなんかな。だけどそのシミュレーションをするのに行列を使ったら元も子もないので、どうするの? 頭が働かないから行列におまかせしていたんだけど、どうしたらいいの?

軸に平行な直線で折り返すのはまあできる。90度回転は x と y を入れ替えたり符号を入れ替えたりで、たぶんできる? 個々の点の座標を求めるのは……?

まあ、TLE 提出を見れば行列って形で式が見えてるんだから、計算できないはずがないんだよなあ。

 提出 #19690206 (AC / 619 Byte / 1497 ms / 103080 KB)

いやー、厳しい。ヒントがあってもいくつも穴にはまって時間がかかる。「まあできる」とか言っていた折り返しも実はできなかった。


ここでやったことと蟻本に書かれていた(けど解らない)「実は、m 項間漸化式の n 項目は行列を用いるのではなく、各項を初項の線形結合で表して繰り返し二乗法を行うことにより、O(m^2log(n)) で計算することも可能です。興味のある人は考えてみるとよいでしょう」に関連はありますか?

 @2021-02-06

移動後の点の X 座標ないし Y 座標を求めるのに、a+x*(b-a)+y*(c-a) の式を使うと遅い。どうせ同じ数の係数を蓄えておくなら、a+b*x+c*y で答えが求まるような係数を用意したい。

でも何を考えて係数を変換していけばいいのかわからない。

a,b, c,d, e,f の初期値を 0,0, 1,0, 0,1 として、操作1~4でどのようにマッピングしていくか。

遅い方速い方備考
操作1b,-a, d,-c, f,-eb,-a, d,-c, f,-e同じ
操作2-b,a, -d,c, -f,e-b,a, -d,c, -f,e同じ
操作3p2-a,b, p2-c,d, p2-e,fp2-a,b, -c,d, -e,f 一部 p2 の省略
操作4a,p2-b, c,p2-d, e,p2-fa,p2-b, c,-d, e,-f 一部 p2 の省略
移動後の座標(a+(c-a)*x+(e-a)*y, b+(d-b)*x+(f-b)*y)(a+c*x+e*y, b+d*x+f*y)引き算が不要

遅い方は各操作で余計なことをしていて、移動後の座標を求めるときにも余分なことをさせられている。そりゃあ遅くなるはずだけど、何を念頭に置けば速い方の式が書けるのかわからない。

遅い方を書くときは、基底となる2つのベクトルを定める3点を移動していくつもりで書いていた。

速い方でも (a,b) の意味はただの点なのでわかる。でも (c,d) と (e,f) に何のイメージを割り当てればいいのかわからない。それこそ向きと大きさだけで位置を定めない、ベクトルそのもの? そうかもね。そうなんですか?


2021年01月22日 (金) オブジェクト指向には、カメラがやっとついたころのガラケーのイメージがある - きしだのHatena」からの「現代のオブジェクト指向の class の割れ窓化と宣言的プログラミング」■副作用の分離(と集中)だと読んだ。ちょっと前に書いたこれも同じ視点でとらえ直せると思う。「「もし~ならこうする、さもなければこうする」という型のコードは2つの「こうする」に無制限に無関係な処理が書けるし、何もしないこともできるし、目的に対して自由度が高すぎる。もっと制限の強い型にはめれば読み手にいらぬ想定を強いることがない。コアとなるコードは「何かを出力する」となるべきであり、その何かを作るのに if 文を書いたり、if 文を含んだ関数を一度だけ呼び出したり、事前に用意しておいたデータファイルを読み込んだりするのが良い」 あっちで出力し、こっちで出力し、とコードの分岐のあちこちに副作用をばらまくのはやめましょうと。全然書けないけど Haskell あたりをたしなむとモナドなんて概念があって、自然と副作用をコントロールするスタイルが身につくのではないかという気がしている。全然、一行も書けないけど。


2021年01月21日 (木) [Ruby] 箱入り娘というパズルがあるそうな。最短81手の初期配置を解く>箱入り娘.rb。何をもって一手と判断されるかはここを参考にした>「箱入り娘/解答」。パッとは書けなくて、じっくり時間をかけた。Ruby 1.8 対応はできなかったけど 1.9 と 2.5 と 2.7 は OK。ここでは最少 138 手の配置が紹介されている>「箱入り娘パズルの攻略法」 それもスクリプトに足しておいた。たしかに 138 手だった。■■■同じく Ruby で解いていた人がいる。「箱入り娘パズルをRubyで解く - yarbの日記」 22分かかるって書いてあるんだけど、s.visited という行を s2.visited に書き換えて8行か9行下に持って行くと、30秒もかからずに終了しましたよ(そして9305手の履歴を表示した)。そもそも Ruby 2.7 では元のままでも5分かからずに(書いてある通りに) SystemStackError が出たのであるが。■■■@2023-10-02 バグみっけ。箱入り娘.rb の 30 行目。Array#uniq にブロックを渡して処理を行っているが、このブロックは uniq メソッドの一部として働くのであって、uniq した結果が渡されてくるわけではないんだよね。Array#split にブロックを渡す用法があるのを知って以来、隙あらば each を省こうと狙っているのだけど、Array#zip と Array#product は良くても uniq メソッドは間違い。処理が重複して無駄になっていた。


2021年01月17日 (日) いつの間にかセンター試験が終わっていた。なくなったという意味で終わっていた。時代は共通一次……ではなく共通テストらしい。

最終更新: 2021-03-02T17:55+0900

[AtCoder] 緑diff精進4問

AtCoder Regular Contest 100C 問題 Linear Approximation
提出 #19496296 (AC / 124 Byte / 173 ms / 36900 KB)
ソートすることに気付けたらあとは基準線をどう上下させるかだけ。
最初は平均をとって考えていたが中央値だった。ひとつだけへっこんだ極端な要素に下駄をはかせようとして、他のすべてがそろってでっぱったら意味がない。+1 するか -1 するか、改善する要素が多い方を選び続ける、その均衡点。
AtCoder Beginner Contest 115D 問題 Christmas
提出 #19497044 (AC / 480 Byte / 63 ms / 14280 KB)
2020年12月にあった PAST の J 問題 長い長い文字列を思い出した。提出 #19035422
ということはこの問題も、クラスも入れ子にしたインスタンスも(つまりは再帰関数が?)不要で解けるということなんだけど、それは解らないので答えはプログラムに聞いた。
天下一プログラマーコンテスト2012 予選CB 問題 ロイヤルストレートフラッシュ
提出 #19497447 (AC / 169 Byte / 65 ms / 14320 KB)
これは簡単。最大でも50枚ちょっとしかないカードなんていかようにも処理できる。
Tenka1 Programmer Beginner ContestC 問題 Align
提出 #19498159 (AC / 215 Byte / 182 ms / 16952 KB)
よくわからない。雰囲気で答えらしきものを求めた。
これを提出するときに1年以上前に D 問題 Crossing に挑戦していたことを知った。提出 #8100494。え? さっぱりわからないんだけど。当時と同じように1時間ちょっと考えてどうにかなる気もしない。

2021年01月15日 (金)

最終更新: 2021-01-16T18:37+0900

[AtCoder] 緑diff精進3問

Coprime はまた解けなかった。WA ではなくなったけど TLE が解消しない。

AtCoder Grand Contest 023A 問題 Zero-Sum Ranges
提出 #19447872 (AC / 107 Byte / 176 ms / 43452 KB)
以前に一度挑戦して TLE になっている。今となってはどうやって TLE を出すのかわからない。
半年前(20200615)まで累積和という概念・単語を知らなかったから、それが理由だろうな。
AtCoder Beginner Contest 160E 問題 Red and Green Apples
提出 #19448291 (AC / 114 Byte / 192 ms / 42816 KB)
リアルタイムで参加した ABC だけど D 問題で詰まったからこの問題は初見。こんなに簡単でいいのだろうか。X≦A、Y≦B という制約がまた親切で、面倒な場合分けを取り除いている。
提出 #19457324 (AC / 94 Byte / 242 ms / 41108 KB)
引数付きの max メソッドを使うチャンスだと気がついて再提出してみたら 25 % くらい遅くなった。用意された罠なの?
diverta 2019 Programming Contest 2B 問題 Picking Up
提出 #19449145 (AC / 184 Byte / 65 ms / 14404 KB)
2019年と2020年に一度ずつ提出して同じように1つの RE と3つ4つの WA をもらっていた。RE は N=1 のケース。WA はたぶん軸に平行な傾きをうまく扱えなかったんだろう。今回は読めていた。

2021年01月13日 (水)

最終更新: 2021-05-04T21:04+0900

[AtCoder] 緑diff精進5問(+α)

AtCoder Problems がお勧めする Moderate な問題(緑difficulty)を上から順に解いた。半年前に解けなかった問題も1年前に解けなかった問題も解けた。だから0完だったこの前の ARC 111 は忘れよう。

AtCoder Beginner Contest 178E 問題 Dist Max
提出 #19414840 (AC / 137 Byte / 319 ms / 28476 KB)
わかるようなわからないような感じが今でもするんだけど、y=x に沿って対極にある2点と、y=-x に沿って対極にある2点を抽出して比較すればいいらしい。コンテスト後に解いた人の感想が目に入っていたのでチートといえばチート。
AtCoder Beginner Contest 152D 問題 Handstand 2
提出 #19421375 (AC / 312 Byte / 63 ms/ 14260 KB)
面倒くさく計算で解いたんだけど、N 個の数を列挙して先頭の桁の数字と末尾の桁の数字でクラス分けして数えて掛け合わせるので解けたらしい。たぶんそちらの方が間違えない。
AtCoder Beginner Contest 114C 問題 755
提出 #19420198 (AC / 210 Byte / 81 ms / 17972 KB)
さっきのと似た問題。これは計算と列挙のハイブリッドで解いたんだけど、そうすると速くもなくシンプルでもなくどっちつかずになった。
そうすると? これを見よ>提出 #15048046 (jajapop さん)。シンプルに列挙して速い。
AtCoder Regular Contest 006C 問題 積み重ね
提出 #19420356 (AC / 95 Byte / 69 ms / 14280 KB)
謎の段ボール。重さと丈夫さが1つの数字で同時に表されている。1の上に2は乗せられないけれど、1と1と1を3つ乗せることはできる。謎の段ボール。
あ、大きさだと考えればいいのかも。小が大を支える不安定な重ね方が NG だと。でも重さって問題文に書いてあるなあ。←どうでもいいから解け。
最適な置き場所は1つなので貪欲法で。
AtCoder Beginner Contest 039D 問題 画像処理高橋君
提出 #19421120 (AC / 242 Byte / 86 ms / 29364 KB)
最近の ABC-D はこういう素直に実装するだけの問題ってなくない? 数学でいじめられたり制約でいじめられたりばっかりじゃない? この問題が今の ABC で出たら difficulty が緑ってことはまずなくて、灰茶がいいところだと思う。世知辛いなあ。

 アナクロニズム

過去問はテストケースが利用できる。DropBox からダウンロードするとコンテストの各問題ごとに in フォルダと out フォルダが解凍される。

ARC111_A フォルダの中がこうなっているとする。

  • in/
  • out/
  • my_answer.rb

そこで次のように実行する。(ARC111_A> はプロンプト)

ARC111_A> attc my_answer.rb

attc.bat の中身がこう。

@echo off
for %%F in ("in\*") do (
	call :run "%~1" "%%~F"
)
exit /b 0

:run
	echo %~1 ^< in\%~nx2
	call ruby27 "%~1" < "in\%~nx2" > "out\%~n1.out.txt"
	fc /A "out\%~n1.out.txt" "out\%~nx2"
	del "out\%~n1.out.txt"
	echo.
exit /b 0

カレントディレクトリの in フォルダの中身を入力として引数のスクリプトを ruby27 コマンドで実行する。出力を out フォルダの同名のファイルと fc コマンドで比較する。

call ruby27 という風に call が付いてるのは ruby27 が exe の名前ではなくて、C:\Program Files\Ruby27\bin に PATH を通してから ruby.exe を呼び出すバッチファイルの名前だという固有の事情から。

別に call でなくて当たり障りのないコマンドならたぶん何でもいいんだけど、call|ruby27 という風にパイプを通すと新しいコマンドインタープリタが起動するので、呼び出したバッチが setlocal してなかったとしても現在の環境(PATH 変数とかカレントディレクトリとか)が汚染されなくなるというハックがある。cmd /C "ruby27 ..." と同じことなんだろうけど、そっちは引数が引数になって二重の引用符が面倒の種だよね。

tc は Test Case の略だけど、 AtCoder の略が at か ac かで定まらないから、attc と actc の両方の名前でバッチを用意してる。ハードリンクにしたら中身の同期に手間もかからないし。

アナクロだけどそれなりに便利。