出力を入力へ

プログラミングに関する自分が考えた事を中心にまとめます

参加記録 ARC103

前回からちょっと時間が空いてのARC103. CとDの部分点を解いて 600(2) 79:45, 533rd 1003 -> 1081(+78) パフォーマンス1537でhighest更新.

C - /\/\/\/

方針自体はすぐに思い付いた. 数列の偶奇で分けて,一番出現頻度が高い数字に合わせて他の数を修正すればよい. 偶奇で同じ数にはできないので,偶奇それぞれで2番目まで出現頻度の高いものをカウントし, 偶奇のそれぞれにて出現頻度が最も高い値が同じならば,偶奇どちらかを2番目に出現頻度が高い数にすればよい.

最初上手く実装する方法あるのかと考えたが なさそうなので愚直に実装した. n も v_i も 105程度なので実行時間の制約は厳しくない.

さっさと実装して提出するもWA,不具合を見付けて修正・再提出するもWA (22:55経過時). 奇遇の最も出現頻度が高い数字が等しい場合に2番目に出現頻度が高い数に修正する処理について, なんとなく分岐処理があやしかったので修正して提出したところACとなった.

正答できたとはいえ,なんとなくで修正して提出する非常にあいまいな対処.

D - Robot Arms

入力例2に助けられた. どういったときに条件を達成できないのか考え, 入力例2を考えて, X_i + Y_i の偶奇が等しくなければいけないことに辿りついた.

配点と他の人の解答状況からのメタ読みで, 600点は無理と判断して部分点狙いでいくことに決定. X_i と Y_i が小さいときはどうすれば条件を満たすアームが簡単に構築できるか考えていたら 腕の長さ1のアームをたくさん並べればいけそうだと判断. それに気付いてからは10分かからずに実装して提出,AC.

と中であきらめて他の事をしていたのがもったいなかった.

Harbor 1.1を1.5にアップグレードする

新しくCNCFプロジェクトに入ったHarborを今まで利用してきた1.1から 現時点で最新の1.5.2にアップグレードする. 今後大きく変更が生じることが予測され, 実際1.6からはDBをPostgresqlに移行する計画なので それまでにプロジェクトの構成を確認しておく.

前提

現在は以下の設定で運用している

  • Harbor1.1.1を利用
  • Docker Registryファイルはローカルファイルシステム
  • Notary / Clairは利用していない

これを以下の通りアップグレードする

  • Harbor 1.5.2を利用
  • Docker Registryファイルはローカルファイルシステム
  • Clairのみ利用し,Notaryは利用しない

Docker Registryファイル(おそらくイメージファイル)はS3などに保存することもできるが今回は変更しない. また,Clairのみ有効化する.

アップグレード方針

詳細はドキュメントを参照.ただし,あまり整備されていない様子なので 読み解くのが大変だった(自分は苦労した).

github.com

結論として,マイグレーションの対象は /data/databaseharbor.cfg. NotaryやClairを利用している場合はこれに加えて/data/notary-db/data/clair-dbが増える様子.

上記データをマイグレーションツールのバックアップ機能でバックアップしておき, マイグレーション機能でDBスキーマと設定ファイルを変換した上で Harborをセットアップ・実行することでアップグレードが完了する.

ただし,設定ファイルのマイグレーションは1.2以降からのサポート. このため自分の環境では一度1.1 -> 1.2 にDBスキーマをツールで移行し,設定ファイルを手動で移行する. その後マイグレーションツールを利用して 1.2 -> 1.5にDBスキーマと設定ファイルを自動移行させる.

1.1 -> 1.5に直接移行できればよかったが, 特に1.1の扱いが他のバージョンとは異なる様子. マイグレーションツールで1.5に移行できないのはもちろん, 論理バックアップしても正常にリストアできなかった. このため,1.1の状態では物理バックアップ (/data/database自体をコピーしておく)しておき, 1.2で動作することを確認した状態で論理バックアップなどを行い 1.5へのマイグレーションの準備を整備する.

アップグレード手順

まずはHarbor 1.1のDBの物理バックアップと設定ファイルのバックアップを行う.

$ sudo tar cfz /backup/harbor-database-1.1.1.tar.gz -C /data database
$ sudo cp ~/harbor-1.1.1/harbor.cfg /backup/harbor-1.1.1.cfg

次にHarbor 1.2へのDBスキーマと設定ファイルのマイグレーションを行う. GitHubのリリースページから 1.2.2の(online/offline)インストーラをダウンロードし, ホームディレクトリにharbor-1.2.2とリネームして展開する. DBのマイグレーションは以下のスクリプトを実行する. 設定ファイルは手動で変更する必要があるので, Harbor 1.1に変更を加えた内容に従い, harbor-1.2.2/harbor.cfgに同等の変更を加える.

マイグレーション実行後は, harbor-1.2.2/install.sh を実行し, Harbor 1.2.2が正常に動作することを確認する. docker-compose psですべてのコンテナがUpであること, Harborページにアクセスして画面が表示されることが確認できればおそらく大丈夫. 動作確認後はdocker-compose downでHarborを停止させておく.

Harbor 1.1の状態でDBの物理バックアップは行っているので大丈夫だが, 必要であればこの時点で論理バックアップを行う. 論理バックアップは以下のスクリプトを実行する.

リストアしたい場合は, /data/database以下を削除した上で 以下のリストアスクリプトを実行すればよい.

最後にHarbor 1.5へのマイグレーションを行う. GitHubのリリースページから 1.5.2の(online/offline)インストーラをダウンロードし, ホームディレクトリにharbor-1.5.2とリネームして展開する. harbor-1.2.2/harbor.cfgでharbor-1.5.2/harbor.cfgを上書きし, DBのマイグレーションは以下のスクリプトを実行する. 今回は,設定ファイルも自動マイグレーションしてくれるので1.2時点での設定内容をそのままに, harbor-1.5.2/harbor.cfgを上書きして1.5用に自動修正してくれる.

マイグレーション実行後は, clairを有効にするため以下のスクリプトを実行する.

$ /home/thaim/harbor-1.5.2/install.sh --with-clair

DBおよび設定ファイルのマイグレーションが成功しており, 必要なコンテナやClairの設定が正常終了するとアプリが動作した状態になる. docker-compose -f docker-compose.yml -f docker-compose.clair.yml ps ですべてのコンテナがUpであること, Harborページにアクセスして画面が表示されることが確認して Harbor 1.5へのアップグレードは完了.

おそらく,1.2などで運用していれば問題なかったのだろうが 1.1という中途半端な(?)バージョンで運用していなかったのが問題だった.

IntelliJ IDEAで複数言語混在プロジェクトを作成する

例えば,1つのプロジェクト内にJavaPythonが混在する場合, デフォルトのSDKJavaにするとPythonファイルでモジュールがUnresolved referenceに, SDKPythonにするとJavaのファイルがコンパイルエラーになる.

これを解決するためには,プロジェクトの設定として 利用するコンパイラ(SDK)を複数指定する必要がある.

利用するSDK一覧の定義として, メニューの File -> Project Structure -> Platform Settings -> SDKs に登録する. 例えばOracle JRE8とシステムのPython 3.5など.

f:id:thaim:20180809032957p:plain

その上で,同 Project Structure -> Project Settings -> Modulesにて 対象プロジェクトを選択し, '+'ボタンから上記手順で追加したSDKを指定する.

f:id:thaim:20180809032910p:plain

これで,JavaファイルとPythonファイルを混在させても IDEがいい感じにコンパイラを使い分けてくれる.

参加記録 ABC104

最近のABCは難し過ぎる. ABしか解けなかったけど,これでレート上がるんだから皆解けなかったのだろう.

AB解いて300(10:38), 576th 956 -> 990(+34), パフォーマンス1214

B - AcCepted

正規表現で解けるかな,なんてことは一切考えず愚直に実装した.

'A', 'C'の文字が含まれている位置の確認はともかく, それ以外の文字が小文字であることの確認処理の実装があまり上手くなかった. 'A', 'C'が含まれていることを確認済なので,全文字列の大文字数をカウントする想定実装がシンプルだが 'C'の位置候補でループ処理することしか考えていなかったので 文字列全体のループを別途作る?とか考えていた.

結局提出したのは,'C'の位置だけ記録して,元の文字列全体を小文字化した上で 'A','C'だけ大文字に変換して元の文字列と一致するか確認する方法. 実装直後に想像以上に汚い実装になったので悩んだけれど 結果は正しそうなのでさっさと提出してしまった.

C - All Green

解説の「中途半端に解く配点は1種類以下であり、それ以外の配点は完全に解くかまったく解かない」が全てだと思う. これに気付けなかったので全探索を諦めてしまったし,最後DPで解こうか悩んだ上で実装できなかった. 考えてみれば上記方針はあたりまえなのでこれは気付きたかった.

実装面ではビット操作による全探索に苦手意識があるのと, 完全に解く問題が与えられた上で,残りスコアを中途半端に解く場合に何問解けばいいかを

int need = (G - s + s1 - 1) / s1;

とコンテスト中にさらっと実装するのは無理だったかな,と感じた. どちらもわかっていれば大した事ではないのでしっかりと復習しておく.

D - We Love ABC

方針はCより簡単だった. DPを利用すること,処理した文字列の位置と処理状況を利用すること は比較的早く気付けたが,その後の実装が上手くいかなかった.

解説のように漸化式を上手く構築できればいいけど, 今回のような少し複雑な式になると,まだまだ解けそうにない. このあたりの感覚はもっと多くのDPを解いて慣れるしかないのかと考えてる.

RocketChatの実装を調べたけどわからなかった

前回の続き.

結局FlowRouterの利用設定がおかしいだろうことはわかったけど, 原因は特定できなかった.

おそらく原因は packages/rocketchat-libにあって, 一次的にはgetRouteLinkが返すリンクがおかしい. ただし,getPermaLinkや directoryのリンクであるonTableItemClickのように出力がおかしいものだけでなく, chatNowLinkroomDataのように正常に動作するものもあるので getRouteLinkがおかしいわけではなく, FlowRouterに設定されたルーティング情報がおかしいのだろう.

各種チャンネルはdefaultRoomTypes.jsで定義されているが, この実装であるaddはおそらく正常に動作している. 他の正常に動作するルーティングを定義するrouter.jsと 比べても特におかしいところはない.

むしろこのルーティングのactionであるopenRoomの 実装がおかしいのではないかとは考えたが,これが何をしているかよくわからず, また特段おかしいところも見付けられなかった.

正直なところ,慣れないフロントエンド,初めてのmeteorで 上手く不具合修正できる気がしない. 今後どのようにデバッグすればいいのだろうか.

meteorチュートリアルを試してRocket.Chatの実装を調べてみた

普段利用しているSlackクローンのRocket.Chatについて, 結構前から動作に影響の大きな不具合が出ていたので頑張ってIssue報告してみた. これ自体は意図は伝わったのか,他にも同様の不具合を報告してくれる人が何人も現れ, これで対処してもらえると思いきや,報告から2ヶ月たっても修正されそうな雰囲気なし.

このままでは非常に使い勝手が悪いので, 自分で修正してみることを視野に検討してみた. とはいえ,フロントエンドはまったくわからないので どこから手を付ければいいのか悩ましいところ. いろいろと調べていたら, Rocket.Chatを実装する meteorフレームワークには 複数のチュートリアルがあることが判明. RocketChatのソースコードを読んでもわからないことばかりだし, かといってJavaScriptから勉強していたのでは時間が掛かり過ぎるので フレームワークの動作からおさえることに.

チュートリアル内容

3種類のチュートリアルのうち,最も基本的なReactなTODOアプリを実装してみた. meteorフレームワーク自体はなんとなく理解できたが, 途中まったく動作せずいろいろと確認してみた結果, チュートリアル内容に誤りがあることが判明. また,同様の不具合としてテストを追加実装しても実行されない様子.

Rocket.Chat実装調査

meteorフレームワークの動作がなんとなく理解できたので それではRocket.Chatの実装も調べてみようと思いきや 当然実際のアプリはより複雑で理解できず.

特にチュートリアルにはなかったディレクトリやインスタンス?が多数登場し どのような仕組みでロードされているのかわからないという, チュートリアルを試した成果がまったくない状況に. 諦めようか悩んでいたところ,やっとファイルを読込む順序や各種ディレクトリの意図を説明する ドキュメントを発見. これを読むことでやっとRocket.Chatの動作がなんとなくわかるようになった.

Issueへの対応

それじゃあ不具合修正も簡単に対処できるかというと,そちらは全く進捗なし. 不具合の原因がmeteorのルーティングまわりを制御する FlowRouterまわりにあることは理解できたが, FlowRouterがおかしいのか,Rocket.ChatにおけるFlowRouterの制御がおかしいのかは切り分けできず.

いろいろと調査しているうちに,時間切れになったので3連休中の調査は一旦終了. ECMAScript2015やnpmまわりの理解も追い付いていないのでまだまだ時間は掛かりそう. このペースで調査を進めて不具合修正できるのが先か,他の人が修正してくれるのが先か.

参加記録 ARC100

記念すべき第100回にて大敗北してしまった.

0完で1001 -> 956. 安定してCD解けるようになりたいと思っていたけど Cが解けないのはきびしい.

C - Linear Approximation

bの候補は b = A_i - i を満たす最小のbと最大のbの間のいずれか => bの候補は最大109通りになるので当然TLE

bの候補は b = A_i - i となる最大N個のうちのいずれか,かつ中央値付近? => 一部でWAが発生(実は悲しさの値のオーバーフロー)

となって,候補はN通りではない?と疑問を持ち始めて悩んでいるうちに モチベーションがどんどん低下していく最悪な事態.

  • 最初からA_i - iと考えておけば問題をシンプルにできたので考察が簡単に進めることができたかもしれない
  • bの候補は考察を基に高々N通りであると判断できておくべきだった
  • そもそも最初の提出がTLEの事を何も考えていなさすぎて酷い
  • intのオーバーフローに気を付けることは競技プログラミングの初歩の初歩
  • 解が中央値であることは考察以前に知識として持っておくべき頻出問題だ
  • コンテストの100分くらい集中力を持続させろ

と,反省点が多過ぎる.