週記(2020/08/17-2020/08/23)

08/17(月)

今日は11時間寝た。寝る子は育つ。縦には伸びていないし質量も変わっていないようなので、どこが伸びているかは謎だ。

atgolferを確認すると、昨日寝る前に縮めたVimのコードがさらに縮められている。

atcoder.jp

ファイル全体をbashコマンドでフィルタするのには、:%!と書く必要があると思っていた。なので、:を省くためにExモードに入っていた。:%!というのは、まず:コマンドラインに入り、%でファイル全体を指定して、!でフィルタをかけることを意味している。

実は!でフィルタコマンドとしての意味があるらしい。つまり、最初の行にカーソルがある状態から!でフィルタコマンドに入り、Gで一番下まで選択すればよい。

change - Vim日本語ドキュメント

確かにそうだ。これは僕も知っているはずだ。なんとなれば、!!!jを使用するコードは目にしていたのだから。

悔しいので、試しにソートまで含めてすべてbashコマンドで書くとどうなるか、試してみる。これはsor nsort -nになって直感的には長くなるのだが、bashのパイプを活用することで:やら!Gがいくらか省ける。

atcoder.jp

縮んだ!奇跡的。

明日締め切りの期末レポートがあるので、それに立ち向かおうとため込んでいた講義資料を消化し始める。早々に行き詰まってしまった。3回目くらいからもう難しすぎて手も足も出ないんだが???

仕方ないのでラノベを読む。2冊読んだ。講義スライドは4回目の分までしか終わっていない。もう夜が明ける。助けてくれ。

レポート問題もよくわからない。2問はもっと先に進まないと用語すら理解できなさそうで、1問は言ってる意味は分かるのでやってみようとしたけど、途中で詰まってしまった。

もうダメだ。明日の自分に任せる。ということでコードゴルフをする。先日からJAGの問題を開きまくって、縮みそうなものだけ別タブにまとめていたので、それを消化していく。

atcoder.jp

久々にsedを書いた。sedは言語アップデートによって(コード長の意味で)明確に不利益を被った言語の1つ。空文字列のラベルが使用できなくなったのだ。リンク先のコードでは5,7行目にあたる。

以前は:;s///;tでループできていたのだが、今はラベルが必要不可欠なので、:tの後に適当に1文字入れておく必要がある。+2B

これの現最短は38Bなので、言語アップデート前に気づいていれば36Bだったのにな……と悔しがっていたら、Vimで軽々32Bが出せた。

ツイートを遡ると、AtCoderの言語アップデートは5/13夜~5/14昼に一瞬行われてすぐ巻き戻された後、6/18の夕方に改めて行われたようだ。

なぜこのような話をするかというと、もともとJAGのいくつかの問題は提出言語がC/C++Javaだけに制限されていたからだ。この制限は言語アップデートやその巻き戻しで(うっかり?)解除された。提出一覧を見ると、それ以前はCからsystem関数を呼び出すコードが最短になっている。

つまるところ、旧sedで提出する機会というのは言語アップデートで制限が解除された後に巻き戻される5/14から、改めて言語アップデートが行われた6/18の間しかなかったのだ。とはいえこの期間中にAWKPerlで提出しているのだから、sedで縮むことに気づいてもよかったようなものだが……。まあVimで縮んだのでもう気にすることはない。

08/18(火)

起きたら午後7時だった。期末レポートがやばい。期限は今日が終わるまでだ(23時59分までなのか23時59分59秒までなのかはわからない)。

頑張って書く。半ば諦めているので、半分も解いていないが、出すことにする。実家にいるので父のスキャナ付きプリンタでスキャンする。もう提出期限まで30分もない。

最初のスキャンでは1ページに死ぬほど時間がかかってしまったが、これは写真などをスキャンする設定のままだったためで、シャーペンで書きなぐったレポートがフルカラーであったり高解像度であったりする必要はない。そこを直すとまともな速さになった。

PDFファイルになったのが期限まで残り15分の頃。確認すると、解像度を下げすぎたようで一部文字がかすれてしまっている。僕は十分判読できると踏んで、父にメールで自室のパソコンに送ってもらうよう頼み、提出作業に入る(仰々しい言い方をしているが、classroomの課題ページにアップロードするだけだ)。父は解像度を少し上げてもう一度やり直すというが、とりあえず提出はする。

解像度が少し上がったものをスキャンし終わったらしい。残り7分くらいか。確かに文字のかすれは少なくなっている。再度メールで送ってもらい、取り下げ→提出をした。この時点で期限まで残り5分を切っていたようで、「期限に間に合いました」という通知が出た。

これで今期の課題はすべて終了した。まごうかたなき夏休みだ。コードゴルフをする。

JAGの問題で残っていたものを全部確認し、AtCoder ProblemsでいうところのOther Contestsに入る。下からやっていく。

よほど簡単な問題は、dcで縮めようとして5/14の朝方に一度すべてさらっている。それからテクニックの改善に従って縮められたものも数多くあるが、今回の主眼はそこではなく、以前さらった時にはあまり気にしていなかった中難易度の問題だ。とりあえずAC済みのものをすべて開いて、縮みそうなものは片端から縮めていく。Other Contestsは死ぬほど多いので、この作業もかなりかかることだろう。

そうこうしているうちに夜が明けた。そろそろ生活リズムの逆転が気になってきたので、今日はこのまま昼過ぎまで起きて、一周させることにする。

もう朝なので、物音を立てても問題にならない。部屋の整理をすることにする。以前、仙台から既読本を実家に運んでおいた。これが段ボール詰めになっているため、本棚に入れる。

昨年から質より量を標榜して、ライトノベルばっかり読んでいる。やっぱり本棚が埋まると気持ちがいい。実は本を読むのが好きというより本を本棚に並べるのが好き。

またゴルフをする。今日はPerlの話をする。

atcoder.jp

これは言語アップデート前のコードだが、このコードは今の環境では動かない。

例えばコードテストなどでprint${chr 6}などと実行してみればわかるが、ASCIIコード6の文字の特殊変数は初期値が2だ。さらにmutableでもあるので、掛け算をするときの変数としてなどそこそこ使いどころがあった。これを利用して縮めているコードは探せばいくらか見つかるだろう。

ところが、Perlのアップデートによって、chr 6をコード内にそのまま埋め込もうとするとREになるようになってしまった。ということで、このテクは今後使えない。他にも違法になった書き方があって、Perlゴルフも言語アップデートによってコード長の面で不利益を被ったといえるだろう。

さて、Vimで空白区切りの単語を改行区切りに直す方法について、以前このようなことを書いた。

オプション'textwidth'による各行の長さの制御だろう。

週記(2020/08/03-2020/08/09) - kotatsugameの日記

これはちょっと違うらしい。ウィンドウ幅2で分割した後、そこで:echo &textwidthなどしても0のままであることが確認できるのだ。結局よくわからなくなってしまった。オプションの値は変更しなくても、視覚的に幅が2になっているので、それに合わせて切り詰められる感じなのか?

午後3時、そろそろ眠くなってきたので、寝る。

08/19(水)

この日記は、僕が起きてから寝るまでを1日として書いている。なので朝寝て夜起きる生活も連続した1日として記録していたわけだ。

8/18に徹夜して、8/19に寝て、次に起きたのは8/20だった。主観的には8/18に寝た後起きたので8/19だが、現実的には8/20である。このように、現実と丸一日ずれてしまった場合、自分の中で8/19を飛ばすと定めている。

よってこの日記でも8/19は存在しないものとする。

08/20(木)

夜明けとともに起きる。これは嘘で、中途覚醒を繰り返しており、睡眠時間的には10時間弱くらいのはず。本当は無理やり生活リズムを矯正して定着させるためにもっと長く寝ておきたいのだけれど、こういったときに限って半日眠るみたいなバカなことができなくなる。ままならない。

ちなみに中途覚醒したときはたいていatgolferを確認している。縮められているものを見つけるとスマホで確認してしばらく考え込む。こんなことしてるから眠れなくなるんだ。僕が寝ている間に取られたもので、一つとてもショッキングなやつがあった。

atcoder.jp

99@:の代わりにgフラグでやっている。いやそれはそうなんだけど、アンカーの外側も位置として消費されるから繰り返し適用しないとだめだと思い込んでしまっていた。これはPerlの先読みでも同じことが同じようにできるので、ちゃんと正気にならなければいけなかった。アンカーを使って満足してしまっていた。

起きてからラノベを一冊読む。今日はお出かけの日。母に車を出してもらって書店と古本屋に行く。

買った本のうち常識的な冊数は仙台に送ってくれるらしいので、持ち運びを考えずに買いあさることができる。仙台に帰ったら次いつ書店に行くかわからないので、この隙に積んであるシリーズの続刊も構わず買い込むことにする。つまり、すぐ読むことを考えなくてよくなったからだ。

ラノベの新刊コーナーをざっと見て、新しいシリーズにも手を出す。表紙と裏表紙のあらすじを適当に読んで、適当にカゴに入れる。リアルの本屋さんでないとこういうことはできない。16冊買った。

昼食を食べて古本屋に行く。仙台でも駅前のブックオフにはよく行っていたのだが、最近はご無沙汰。僕が最後に行ったときのものと比較すると、富山で僕が行く古本屋はラノベがよく揃っているように思う。まあ一揃いのものを買うのにはネットの古本サイトが最も良いのはわかりきったことだが、この古本屋の強みはそこではない。

古くて売れ残っているラノベは、値段を下げられて別の棚に移されるが、その棚がかなり広く、しかも一律一冊50円なのである。50円!僕がここに通い始めたのは高校生のころだが、その時は100円だったような気もするが、いつの間にか50円になっていた。これはとんでもない安さだ。仙台のブックオフは100円にしかならない。やはり政令指定都市は違うのか……?

で、帰省のたびにここに来て、気が狂ったように買いあさっていくわけだ。僕は基本的に本棚が埋まればよいので、どんなラノベでもよいのだが、一応選ぶにあたって基準はある。それが、シリーズ全巻揃っていることだ。

いや結局揃っているものを求めるのならネットの古本屋を使えよ、とはならない。なぜなら、ネットの古本屋では、本棚の端から端までずーっとラノベを確認していくようなことができないからだ。欲しいものをこれと定めて、検索してさっさと買うのがネットなら、リアルの古本屋は腰を据えて玉石混交の本棚から玉っぽいものを選び出す場所だ。

玉っぽいものとは、これは先ほど書いた定義、つまり全巻揃っているシリーズのことだ。まず適当に1巻があるものを探して、表紙やあらすじを確認しつつAmazonで検索、全巻揃っていればとりあえず買う候補に入る。そのあと候補が増えすぎたなと思えば、適宜表紙とあらすじから判断していくつか棚に戻しておく。これを繰り返して買うものを選ぶ。どうせ50円なのでいくら買ってもOK!ちなみにこれをやると、1巻や2巻で打ち切られたシリーズが大量に手に入る。続刊が出ないことがほとんど確定しているので、結構適当かつ気楽に読める。全4巻を超えるとウッとなる。

で、50円の棚から30冊選んだ。本当はラノベじゃなくて一般の文庫の棚も見に行きたいが、さすがにこれを持って移動するのはつらい。一旦レジを通して、母の車に積み込むこととする。で、レジに行ってみると、50円の本がなぜか半額になった。かなり意味不明じゃないか?100円で4冊買えるってマジ?

半信半疑のまま750円支払う。この後もう一回一般の文庫の棚に行ったが、それほど時間もないことだし、適当に見て少しだけ買う。1冊50円じゃないしね……。ここでは8冊買った。

まとめるとこんな感じだ。

レシートを細かく見るとわかるが、30冊とさんざん書いているのに29冊で会計されている。これは、もう1冊を一般の文庫と混ぜて買ったからだ。簡単のためにまとめて30冊と言っている。

家に帰ってきて、さっそく買ってきた新刊から「デート・ア・ライブ アンコール10」を読む。完結済みシリーズの短編集で、後日談もあるらしい。このシリーズは本当に好きなので、大変楽しみにしていた。

読み終わったらもう眠い。何とか風呂に入って、寝る。

08/21(金)

午前6時に起きてから夕方までずっとラノベを読み散らかしていた。最終的には5冊読んで、1冊2時間くらいか?高校生のころ、一時期ものすごく読むのが遅かったことがあって、それに比べたらだいぶ速い。つまりそれだけ適当に読んでいるということだ。まあラノベなのでOK。前の巻の内容とか、かなり忘れるようになった。

ご飯を食べて、しばらくコードゴルフっぽいことをしていたら、yukicoderがあるようなので、参加する。2週くらいレポートやってて出られなかったので、久しぶりだ。

よくわからなかった。眠いのであんまり考えていない。Cのテストケースのミス(制約違反)で最後通らなくてちょっと残念。

atgolferでいくつか似たような短縮が流れてきて、取られっぱなしはよくないので僕も似たようなのを探して縮める。結局僕が持っているやつを縮めてるだけなので、大赤字。

昨日買った本を「買った本の記録」に追記する。こういうことをしているのは僕の自己顕示欲の発露。上のほうで本棚やら本の購入やらを盛んに話題にしたのも、そう。最たるものは読書記録の公開である。

明日はABCがあるが、この分だとちゃんと起きていられそうだ。生活リズムを1周させると、しばらくは夜のイベントに参加するのが難しくなってしまうので、ぐるっとさせるならば週の初めが一番だ。

08/22(土)

昼過ぎに起きる。もう生活リズム壊れてきてないか?

yukicoderでコンテストがある。途中で切り上げて、携帯電話の充電器を買いに行く。あんまり元気がないので、車の中で考察だけする、みたいなのはしなかった。

帰ってきて、コードゴルフをしているとABCの時間になる。

Fが解けなかった。全完streakは19で切れた。悲しい。

ある程度貪欲した後補正する、みたいなことを考えていて、遅延セグ木を生やしたりして4700Bのコードを書いたのだが、全然合わず、そのまま終了した。解説を読むと、DPの高速化らしい。これなんでわからなかったんだろう……。とは言いつつ、実装のときは結構苦労した。すでに更新したDPテーブルを再度参照して壊れたりして、結構実装に気を遣う。

B問題はクソデカ整数が9で割り切れるか判定する問題だ。そのまま整数として扱うと、dcRakuではTLEしてしまうが、RubyPythonは問題ない。さらになんと、bcでも問題なく扱えるようだ。dcbcの内部実装だ、みたいな話をどこかで聞いたことがあって、それを信じているので、dcでTLEしてbcでTLEしないのはかなり意味が分からない。

AtCoderbcは起動時に-lオプションが指定されている。これがないと三角関数などが使えず役に立たないのだが、逆にこれを指定しているのでscale=20になって、余りをとる演算ができない(正確にはできないのではなく余りが小数になってしまう)。別の言語からbcを呼び出せばよい。

ということで、Vimからbcを呼び出して、再度VimのほうでYesNoの場合分けをするコードが最短になった。これは人が縮めているのを見てすかさず短縮、横取りしたやつだ。

atcoder.jp

そのあともコードゴルフを続けていると、日が昇ってきてしまった。もう生活リズムが逆転しそう。本当にどうしようもない。

08/23(日)

午後7時に起きる。生活リズム破壊、完了……。

今日は何もない。予定もなければコンテストもないしやるべきこともない。ラノベを読みつつコードゴルフをする。

読んだラノベは1冊だけ、「恋愛する気がないので、隣の席の女友達と付き合うことにした。」。あとがきによると、表紙のイラストに何か仕掛けが施されているらしいのだが、全然わからない。

atcoder.jp

sMのタイミングをずらして、各ループの最初に行うことにする。一番最初はスタックが空なので影響はなく、途中もスタック操作は変わらない。最後、sMされずに積まれたままのものが残ってループが終わる。これはまさに出力したいものだったため、そのままpして終わり。以前までは、毎回ループの最後にsMして、抜けた後lMpしていた。

たったこれだけで-2B。こういう変形はかなり苦手なので、結構やり残しがあった。頑張って探して縮めた。今回は目grepじゃなくてgrepしたので手軽だった。目grepは神経をすり減らすが、予期せぬ更新を見つけることができたりする。

そのままずっとコードゴルフをし続けていたら、月曜日の午後5時になった。こんなに素早く生活リズムを一回転させたのは初めてかもしれない。たぶん8/24は8/19と同様に日記から消えるだろう。

これを書いている途中に念のためatgolferを確認したのだが、確かに、19時間前の更新から絶えずコードを縮め続けている。300Submissions弱。

今日はOther Contestsの続き、また古いものからどんどん見ていた。とんでもない個数の自明な短縮・言語変更による短縮があって、こんなの早い者勝ちだなあという気持ちになる。大半は自分のコードがすでに最短なので、それをさらに縮めることになる。そうこうしている間にも僕の最短コードがいくつか取られていくため、かなり頑張らなければ1日の収支はたいていマイナスになる。今日はさすがにプラス。