ICPC 2023 Asia Yokohama Regional 参加記

はじめに

この記事は 東京高専SPC同好会/プロコンゼミ老人会 Advent Calendar 2023 の記事です。

2023/11/25-2023/11/26 に開催されたICPC 2023 Asia Yokohama Regionalに筑波大学からチーム "GoodBye2023" で参加し、9完9位でした。 本記事ではチーム構成やコンテスト中の動きなどについて記していきます。

チームについて

  • 僕: 引退勢・アルゴ黄
  • Aくん(仮名): 引退勢・アルゴ黄(highest橙)
  • Bくん(仮名): アクティブ勢・アルゴ橙

の3人で組みました。 記事に名前を載せていいか聞いてないのでチームメンバーは仮名で呼ぶことにします。

チームメンバーのやる気があまり無かったこともあり、一度のみの練習で競技に臨みました。

コンテスト

事前の打ち合わせでは僕が事前準備担当でAくん・BくんにそれぞれA・Bを解いてもらう手筈だったのですが、Ubuntuにユーザー名とパスワードを入力した時点でPCがフリーズ。 どうしようもなさそうだったのでスタッフを呼んでPCを再起動して貰いました。 これが原因で僕たちのみ3分延長となったのですが、トラブルが起きている間も問題文を読むことはできていたので少し得だな~と思ってました。 再起動後にはAの解法が出ていたので僕は準備をせずにC以降の問題文読みをすることになりました。

C問題以降について、問題ジャンルと制約、可能ならおおよその難易度感を伝えるつもりで雑読みをしていきます。 適当に読んでいくとDが明らかにRun-Length Grammarの話でニヤニヤしつつ、Fがかなり楽そうな見た目をしていることに気がつきました。 Aが解けた時点で順位表を見るとFが1チームに解かれていたので簡単だと確信し手を付けることにします。 少し考えるとランレングス圧縮のように考えれば良いことがわかり、ABを解いてもらった後に実装、バグらせずに無事Fを解くことができました。

後は問題を読みつつ順位表と相談して解けそうな問題を探します。Dが阪大のチームに解かれており、そこで少し考えると O(n3) の区間DPが思いついたので実装を詰めます。 Aくん・Bくんはこの時点でEの考察を終え実装をしていたのですが、少し計算量が悪いらしくTLE。 Eの実装・計算量改善とDの実装・バグ取りをPCを交互に触りながら行い、90分時点で両方ACが出ました。

DEの実装をしている間にAくんがKを解いたらしく、概要と雑解法を聞いた時点で実装を任せ、Bくんと一緒に他の問題について考えていきます。 残りでACが出ている問題ははGHJで、順位表を見る限りだとGが少し楽そうです。 Jについてはいくつかの仮定を信じるとHLD+min-add遅延セグ木で解けるということを教えてもらいましたが、写経コストと嘘解法の可能性を考えて放置。 Hも燃やす埋めるに帰着できそうなことを教えてもらったので、辺の張り方などを詰めてもらうことにしました。 Gも2人で考察をしていると実験結果次第で解けそうなことが分かり、KのACが出たところでBくんに実験コードを書いてもらうと実行時間が十分間に合いそうなことが判明、そのまま実装をお願いしました。 1ペナこそありましたがGも無事AC。

この時点で競技開始から2時間半ちょっと。残りの可能枠はHIJで、JとHはおおよその解法が出ているがライブラリ写経が必要な状態です。 ここでAくんにDinic+HLD+Lazy Segtreeの写経を全て投げます。本来なら実力的に僕がやるべきなんですが、僕はUSキーボードに不慣れでまともに写経ができない状態でした。 Jを考えていると貪欲を信じて良い気持ちになれたので貪欲の実装部分をすぐ実装できるよう簡単に紙コーディングをしていきます。BくんはHの具体的なグラフ構築を詰めている状態です。 写経が終わったのでJを書くと一切バグらず一発で動き、半信半疑のまま投げるとなんと一発AC。 その後に実装してもらったHも問題なく一発でACを得ることができました。9完。

一桁順位もほぼ確定したので安心しつつ、最後の45分でIを考えます。 途中まで線形計画や行列の気持ちになって迷走していたのですが、比率が極端に偏っているものは作りようがないという点を考えるとうまく貪欲したい気持ちになってきます。残り20分しかないので細かい実装の仕方も分からないままコードを書き、途中でAくんがもう少しマシな方法を思いついたので実装役を交代します。 残り15分程度のところでBくんが想定解と同じベクトルを使った解法を思いつき、それを信じて実装役をもう一度交代。 コードは書ききったけどバグっている状態でアディショナルタイムを終え、コンテスト終了となりました。

結果・感想

9完9位でした。僕達の実力と練習量を考えると大成功と言えると思います。 ただもう少しで10完銅メダルだったこともあり、さらに良い結果が出せた可能性を考えると後悔もあります。

僕は来年から外部の大学院に進学するのでここでICPC人生は終了という気持ちだったのですが、実はAsia Pacific playoffに参加できる確率が結構高いらしいということを後で知りました。どうやら2023年でGoodByeとはならなかったようです。 アジア地区予選を終えチームメンバー全員のモチベーションも高いので、チーム練も行いながら次のコンテストに向けて頑張っていきます。

高専プロコン (procon28~procon30) の競技部門を振り返る

はじめに

この記事は 東京高専SPC同好会/プロコンゼミ老人会 Advent Calendar 2022 4日目の記事です。

本記事の目的

本記事では、私が高専時代に参加してきた全国高等専門学校プログラミングコンテスト競技部門の問題・解法などを振り返っていきたいと思います。
懐古のために書いている記事ではありますが、この記事が後年の参加者の助けになれば嬉しいです1

procon28(2017年 大島大会)

この年はprocon27に引き続いて木工パズルを解く問題で、「画像認識でパズルのピースを埋めるパート」「探索でパズルの解を探すパート」のそれぞれの処理を上手く行う必要がありました。また、得点の低下と引き換えにヒント情報を得る事ができ、ピースの形状情報ヒントを得る事で前者のパートを省略する事が可能でした。
僕はそれぞれのアルゴリズム部分には特に触れていないのですが、前者は木工パズル特有のカット時誤差・スキャン時の測定誤差などがあってかなり厳しく、後者のパートはビームサーチ等で解けたそうです。

当時は高専1年で入学時点ではプログラムもロクに書けない状態だったのですが、2つ上の @_nosita 先輩に誘われてチーム「Cult of the Part Parrot」で参加する事になりました。(本選メンバーには含まれていません)
QtとC++での開発で、僕や他の一年生はビジュアライザを書いたり問題の自動生成をしたりしていました。リポジトリこれ です。

大会では産技品川の方が画像認識パートの輪郭抽出・エッジ検出等を高精度で行った結果唯一ヒント無しで問題を解き優勝、2位以下は形状情報を使ってパズルを完成させており、僕たちは決勝5位で特別賞となりました。

procon29(2018年 徳島大会)

この年も競技部門に参加しました。チーム「人間の力」のチームリーダーをして、アルゴリズム・ビジュアライザ等諸々を書きました。 リポジトリこれ です。

今回の競技はグリッド上での2人対戦陣取りゲームです。各マスには得点が振ってあり、プレイヤーは複数体のコマ(エージェント)をターン毎に動かしながら陣地(タイル)を確保していきます。 自分が確保した(エージェントが踏んだ)マスの得点に加えて、自分のタイルで囲んだマスの得点ものチームの点数となるため、基本的に高得点のマスを踏みつつ要所要所で囲んでいく戦略が重要になる、という展開が想定されていたと思います。
と、ここまで書くと良いゲーム問題のように感じてしまいますが、実態は大きく異なりました。

まず、このゲームですが、会場に1マス50cm程度のグリッドが物理的に存在し、その上でグリッド上に紙製のタイルを置いて戦います。競技部門は例年3人チームで参加するのですが、そのうち1人が司令塔としてグリッド外でパソコンを操作、残りの2人は実際にグリッド上でコマとして動きます。 また、司令塔はエージェントに次の行動(移動・タイル削除など)を指示する必要があるのですが、この情報伝達には音声やその他通信を使う事ができず、A4サイズのトランプを用いて行う必要があります
ターン毎に盤面は変化していくのですが進行中の盤面状況は与えられないので、コマとタイルの動きを目視して盤面の変化を確認し、パソコンを操作して手元のソフトウェア上に盤面を反映する必要があります。一度でも盤面入力を失敗すると手元と実際のフィールド情報に齟齬が発生してしまい悲惨な事になります。
各ターンでは「前ターンでの4人分の行動の確認」「手元のパソコンへの入力」「次の手の決定」「味方コマへの行動指示」を全て行う必要があるのですが、ターン間の猶予時間は10~15秒程度しか存在せず、ほとんどのチームは盤面の入力すらままならないまま、アルゴリズムの段階にも辿り着けずに競技を終える事となりました。
大会2日目になると上位チームは操作に慣れてうまく通信・盤面反映ができるようになったのですが、それでも相手の動きが簡単に分かってしまう事やそもそもパソコンを触っている余裕がない事などが原因で、人間がその場その場でアドホックに考えて行動する方が強いという結論となってしまいました。

募集要項に「メンバー間の頑健かつ効率的な通信方法が勝利のカギになります。」と書かれている通り、運営の想定では相手のトランプの札から移動方向を推測してメタを張ったり、それができないように分かりやすく突破が難しい暗号化方法を構築したりすることを考えられていたようなのですが、たかだか15秒の間にそんな芸当ができる訳もなく、適当に選んだトランプを持って腕を移動方向に大きく振るような方法で通信をするチームが上位を含めほとんどを占めていました。
見栄えを良くするために導入したであろう人力要素でしたが、各タイルの得点が競技者以外に見えない事からそもそも試合中はどちらが優勢なのかすら分からないような有様で、講評では審査委員長の神沼先生から「競技部門は何をやっているか分かりづらかった」という感想が飛び出したりしました。

私達のチームは夏休みに産技品川と模擬試合をやったり直前に部屋を借りて人力操作の練習をした結果「これどうせまともな試合にならないんじゃね……?」という結論に辿り着き、盤面の手入力が簡単なUIの整備に力を入れたりしていました。その甲斐あってか予選時点でそこそこまともな試合ができて決勝トーナメント進出、2日目は対戦相手が操作に慣れた事もあり少し厳しい試合もありましたが無事決勝までたどり着く事ができました。
決勝ですが、自分がQRコードで読み込んだ盤面を誤って180度回転させた状態で戦ってしまい、仙台名取にボロ負けしてして準優勝でした2。  

ちなみに使用したアルゴリズムは簡単なDP・DFSをベースにしたもので、陣地を囲むと手に入る領域ポイントはアルゴリズム上では無視していました。アルゴリズム人力の補助として運用し、半年間かけて鍛えた人間の判断力を活かして戦っていきました。

この年は問題が凄くて最早アルゴリズムで戦うとかそういうレベルではなかった印象です。 今後はこのような問題が出ない事を願っていますが、もし出題された場合はアルゴリズムによる解決に固執せず、早い段階で人力に振りきってしまうのが良いと思います3

procon30(2019年 都城大会)

この年もチームリーダーとして参加しました。チーム名は「独立行政法人国立高等専門学校機構東京工業高等専門学校」です。今回も昨年と同じくアルゴリズムやビジュアライザをゴリゴリ書いていました。 リポジトリこれ です。

今回の問題は前年と同じ陣取りゲームで、物理的な要素がなくなりサーバーを使って通信するようになった所が大きな変更点です。 得点に関する基本的なルールはほぼ変わりませんでしたが、扱うエージェント数が増えたりターンの間隔が短くなったりといくつかの細かい変更が行われました。

今回の問題では物理要素がなくなったため純粋なアルゴリズムの要素が強くなると考えられ、実際に様々なアルゴリズムを実装して性能確認を行ったりしていました。 コードを書いていく中で領域ポイントの判定(タイルが囲んでいる領域の判定)が非常に重い事が課題となりました。 これは領域ポイントを考慮するアルゴリズムでは避けられない問題であり、かなり厳しいです。

結局この課題は10月頃まで解決できず決定的な手法も見つからないような状態だったのですが、ここで「別に人力でどうにかすればよくね………?」という結論に至り、その方針で考え直す事にしました。
その結果、去年と同じくDPやビームサーチをベースとしたアルゴリズムを用いて(領域ポイントを考慮しない)自分と相手の行動を求め、盤面を見ながら人間計算機の力で適宜修正していくという手法に落ち着きました。
人力を混ぜる都合上UIは極力使いやすいように整備し、サーバー関連の動作確認も念入りに行いました。特にサーバーとの通信は失敗しているチームが多く、予行演習の段階では7割程度のチームが通信できていませんでした。

大会では順調に勝ち上がり、予行演習から決勝まで意図的な敗北を除けば全勝で優勝する事ができました。また、同時に参加していた課題部門・自由部門についても東京高専の他チームが最優秀賞を獲得し、全部門で最優秀賞という結果になりました。

余談ですが、NAPROCK国際プログラミングコンテストという(高専プロコンと運営が同一の)プログラミングコンテストが存在しており、例年は10月の高専プロコンと同時開催されていました4。 今回はNAPROCK国際プロコンが初の国際開催となり、私達を含む高専プロコンの上位チームは2020年にベトナムハノイで開催される予定であったNAPROCK国際プロコンに招待される事になりました。

procon31以降

当時~2022年現在の東京高専プロコンゼミでは3年生でプロコンから引退する慣習が存在していたため、2020年以降は高専プロコンには参加していません。
一応覚え書き程度に記しておくと、2020年3月から流行した新型コロナウイルスの影響でNAPROCK国際プロコンは中止となり、procon31はオンライン化、競技部門はその都合で中止となりました。 また、その翌年は競技部門が復活したものの完全オンラインでの開催となりました。
競技部門の問題はprocon25を元にしたスライドパズル+画像復元問題であり、強い競技プログラマの方が優勝・準優勝されていました。

おわりに

高専プロコン競技部門について振り返りました。

高専プロコンの問題は例年

  • 問題中の定義が不明瞭だったり
  • 人力要素を入れた方が強かったり
  • 実際に解けない最悪ケースがルール上存在したり
  • テストプレイされているとは思えない内容だったり
  • 参加者のレベルと問題の難易度に大きな差があったり

するので、現役の方は苦しんでおられると思います。頑張ってください。
競技の問題については酷いものは本当に酷い(僕の参加分だとprocon29など)のですが、 近年は毎年ちゃんと考察して良いアプローチを取ったチーム(いわゆるアルゴ勢のいるチーム)が順当に上位に来ているような印象があります5
また、老害的なアドバイスですが、現役の方は

  • ルールに関する質問はドシドシ投げる
  • サーバーを使う競技の場合は事前に十分テストする
  • 操作パートが快適にできるようUI部分を整える
  • 人力を入れた方が強い場合を考慮する
  • 終盤の限界開発をしない

などをしておくとよいと思います。

カスみたいな問題に対してキレながら実装していた事も今となっては良い思い出と言えなくもない気がします。開発期間中は苦しいと思いますが是非頑張ってください。


  1. 高専プロコン競技部門では過去問題のリメイク再出題がされる事が多く、僕も先人の参加記を読んでアイデアを貰ったりしていました
  2. 操作ミスを言い訳にするの本当に負け惜しみっぽくて嫌なんですが、実際にこのミスが原因で数百点差がつきました。決勝後に教員に「これ誰が悪いんですか」みたいな事を言われてつらい気持ちになったのを思い出しました。
  3. コンテストとしてどうなんだ……という気持ちにはなりますが、過去に何度も前例がある以上人力とどうにか向き合うしかなさそうです
  4. 海外チームがオープン参加のような形式で参加していたり表彰式で2回同じ表彰をしたりしてるアレです。僕の入学前のタイミングでは国内の他大学も参加可能となっており、procon25では東大チームが優勝していたそうです。
  5. こう書くと自分の事を褒めてるみたいでかなり微妙なんですが、特にここ数年 (procon32,procon33) はアルゴリズマーの方がちゃんと競技をされていて凄いです

ICPC2022国内予選 参加記

はじめに

ICPC2022の国内予選が 7/8 (金) 16:30-19:30 に行われ、筑波大学からチーム otagai_tasukeai として参加して15位となりました。

チームについて

前から知り合いで全員の熱量がほぼ同じという理由で組みました。 メンバーのレーティングは上から2350,2050,2050ぐらいですが、全員が一年以上の間ほとんどコンテストに出ていないので実力はもう少し下だと思います。
チームメンバー全員が「国内予選に通って横浜に行ければそれでいいかな……」ぐらいのやる気だったため、模擬国内以外の練習は (個人・チーム問わず) 全くやっていません。

コンテストの流れ

まずは他の2人にA,Bを任せてCを考える事になっていたので、コンテスト開始と同時にCに読み始めます。
Aを解き終わったチームメイトに概要を伝えて少し考えますが、すぐには解法が思いつきませんでした。 僕たち二人が得意でないかつもう一人なら解けそうな問題だったので、もう一人に任せてD,Eを読む事にします。
一瞬Eを眺めた後、Dを誤読防止のため二人独立に読んで問題設定の確認を行い、考察をします。
この辺りでBが解き終わり、彼に状況を伝えてCを考察して貰うと数分後に解法が出てきたので、解法の共有・確認をした後に実装を頼みました。
その後しばらくするとチームメンバーがDのアイデアを思いつきましたが、僕の理解に怪しい所があったため一度確認をしたい気持ちでした。

Cが通ったタイミングで作戦会議を挟みます。二人にDの議論をして貰う事にし、僕はEを考える事にしました。
Eのアイデアが思いつかずに唸っている間に二人がDを異なるアプローチで並列に解き始めたため、ランダムテストのためにDの愚直解を用意しました。 先に実装完了した方の解法がランダムチェッカーを通ったので提出し、残り85分でDが通りました。

筑波内最速の4完かつ他チームがDを通しても時間差で勝てそうだったため国内予選通過をほぼ確信し、落ち着いた状態で作戦会議をします。 Fが構文解析かつ阪大の2チームが通している事から実装問だと判断し、ある程度の方針ができた時点で重実装が得意なメンバーに実装して貰い、さっきと同様に僕ともう一人でEを考察する事にします。 二人で考察していると大まかなアイデアが生えたので実装を頼み、自分はEとFのランダムチェッカーを書く事になりました。 EのランダムチェッカーができたタイミングでEの解法の細かいミスに気づき、適当に修正をしながらFのチェッカーを書きますが、残り時間がわずかになってしまったため実装を諦めました。
残り4分でFの実装が終わりAC、15位に浮上しました。Eは実装が間に合わず、5完でコンテストを終えました。

感想

全員のやる気が同じぐらいでコミュニケーションも問題なく、かなり快適でした。
チーム間の問題割り振りや情報共有などはかなり上手く行っていて、能力に起因する問題 (実装に時間がかかった、ある問題が解けなかった等) 以外のミスはほぼ無かったと思います。
Cをすぐに解けなかったのは個人的な反省点ですが、模擬国内では同じ状況で重い嘘解法に手を出してしまったので、怪しい路線に走らずに得意な人間に任せる判断ができて良かったです。
模擬国内と本番で一問も問題を解けていないため、横浜では一問解く事を目標に頑張ります。

RISC-Vほぼ互換の自作CPU上で動くなにかを作った

はじめに

この記事は 東京高専プロコンゼミ① Advent Calendar 2021 3日目の記事です。

やった事

ChiselでRISC-Vの命令を一通り実装したCPUを作り、そのCPU上で動くOSもどき (コンテキストスイッチ程度のもの) を作りました。

github.com

github.com

CPU自作

RISC-VとChiselで学ぶ はじめてのCPU自作 の内容をほぼ写すような形で実装しました。
この本はChiselでRISC-V互換のCPUを作る事を目的にしていて、rv32i (RISC-Vの最も基本的な命令セット) のほぼ全ての命令の実装が解説されています。
環境構築にDockerイメージが配布されていたり riscv-tests によるテストの手順が説明されていたりしていて、僕のような専門知識のない人間にも優しかったです。(嬉しい)

www.amazon.co.jp

github.com

本で紹介されていなかったいくつかの命令 (sb命令など) は適当に自分で実装しましたが、今回は並列処理を行わないためfence系の命令は実装していません。mretなども未実装です。
また、CPUに雑に手を加えた時にハザード関連でバグらせるのを避けるため、パイプラインを実装していない物を使ってデバッグを行うようにしています。 (本では5段パイプラインでの実装が解説されていました)

OSもどき

ここまで実装するとCの普通のコードが動くようになったので、この上でなにか動かしてみます。
とりあえず今回はコンテキストスイッチがあり、タイマ割り込み処理が走ってプロセス切り替えができるOSもどきを作りたいと思います。

開発環境

Cを書きたくないのでRustを使う事にします。
同じ事をされていた他の方 の記事には公式でサポートされているISAがrv32imacとrv32imcのみと書かれていたのですが、調べてみると現在は公式でrv32iへの対応がされており、targetを適当に指定してあげるだけでrv32iのバイナリを吐かせる事ができました。
それ以外の部分は RustでRISC-V OS自作!はじめの一歩 を参考に整えました。
言語自体の安全性や構文の便利さが活きただけでなく、no_stdでもiteratorやOptionなどの機能が使えてかなり満足です。 unsafeで囲めばインラインアセンブラなどを使ってやりたい放題できるのも嬉しい。

権限とCSR周り

RISC-VのPrivileged ISAに合わせて実装をするととても辛そう & 今回は自前のコードしか動かさない ので、今回はオレオレで権限周りの実装を行っていきます。
こうするとCSRを全く使わなくなるので、元の規則を無視して各CSRに入れる値を独自に定義してしまい、雑に値を読み書きするようにしています。(CSRの各レジスタの権限設定はサボっているため、ユーザープロセスでcsrrwなどを使われるとOSが死にます)
また、独自命令を実装しようとするとコンパイル時のtargetを弄らないといけなくて辛そうなので、手抜きの為にCSRの特定レジスタへの書き込みをフラグにCPU側で特殊な処理を行ったりもしました。

プロセス管理

プロセスを雑に [Option<Process>; 16] で管理し、Process構造体には退避時のレジスタの値やpcなどを格納しています。
各プロセスには固定量のメモリを割り当てていて、CSRの特定の位置にプロセス番号を投げるとCPU側に実装したmmuもどきが対応する物理メモリの値を取ってきてくれます。(ページングは実装していないため、メモリを雑に食べていくとすぐ死にます・・・)

割り込み

CSRにタイマ用のレジスタを用意し、一定サイクルが経過するかタスクが終了した場合にinterrupt関数のアドレスに飛ぶようにします。 遷移前にはCPU側でpcの退避を行い、interrupt関数の中でレジスタの退避や各種無効化を行った後にプロセスの切り替えを行います。
切り替え時には現在実行していないプロセスを優先的に選ぶようにしていますが、真面目にやるならProcess構造体に待ち時間などを保持すると良さそうです。

おわりに

CPU自作パートは本当に楽で特にトラブルもなく動かせました、書籍には本当に感謝・・・
OSもどきはかなり手抜きでメモリの動的な割り当てすらできないような状態なんですが、割と考える事が多く、ちゃんと頭を使っている気分になって楽しかったです。 (デバッグはつらい)
結局FPGAを一切触らずにシミュレーション環境上で動かしたため、いつか時間がある時に実機で動かしたい気分になりました。

京セラプログラミングコンテスト (AtCoder Heuristic Contest 006) 参加記

はじめに

2021/11/14の16:00-20:00に行われた 京セラプログラミングコンテスト (AtCoder Heuristic Contest 006) に参加しました。結果は1953482点で、19位でした。



解法

全ての点と (400,400) との角度を求める。
(a,b)の角度 < (c,d)の角度 を満たす配達先のみを反時計回りで巡回するルートを、「ランダムに選んだ1つを削除し、ランダムに選んだ1つを適切な角度に追加する操作」を近傍にした焼きなまし法で最適化する。
これを逆向き(時計回りの場合) でも同様に行い、2つの解の中で良い解に対し、「ランダムに選んだ1つを削除し、ランダムに選んだ1つを改善量が最大となる位置に追加する操作」を近傍にして山登り法で最適化した解を出力する。


コンテスト中の流れ

概要の理解, 初手 (~20分)

まず問題を読んだ。集合を選ぶパートと巡回セールスマン問題を解くパートの2つに分かれている事が分かって、どちらも焼きなまし法が使えそうなので安心した。
2つパートがある問題は解法を2ステップに分けずにうまく一体化する事が大事という話が昔のマラソンコンテストであったはずなので、どうにか両方をまとめて最適化する事を考えたい。
巡回セールスマン問題を含むのでどう転んでも2-optは実装する事になるのかなぁと思ったけど、2-optの実装経験がない+午前中に予定が入っていて集中力が十分残っていなかったので、ひたすら高速化して焼きなますだけの勝負になると勝てなそうで少し不安。
とりあえず配送先1-50を順番に辿るvalidな解を書いてビジュアライザで答えを見たんだけど、それすら少し時間がかかってしまったので反省。

イデア探し (~100分)

とりあえず2-optは実装して損がなさそうだから後で書くとして、その前にビジュアライズした時に分かりやすい+焼きなましに移行しやすそうな見た目の初期解を貪欲法で作る事を考える事にした。
とりあえず近い点対をまとめて扱えると嬉しいのかなと思って近い点対を探したり(a1,b1)と(a2,b2)が近く(a3,b3)と(a4,b4)も近い配送先のペアを出力してみたりしたんだけど、方針が全然思いつかない。
100*100ぐらいのブロックを考えてそこをまとめるみたいな事も考えたんだけど、そうしてもいい解が出せる気がしなくて、困った。
一時間以上考えても何も分からず布団で考えたりしたんだけど、全く分からない。

初回提出 (~120分)

中心との角度でソートして並べれば適切な挿入位置が求まって高速に焼きなましの近傍が出せそうな事に気づいた。 この時点ではすごい良い解法っぽい感覚はなかったんだけど、性能が微妙だったとしてもとりあえず見た目の良い初期解が出せそうなので実装してみる事にした。
頭を使うコードを書くのがつらい+仮実装の段階 なので毎回ソートし直す O(mlogm) の近傍操作を書き、10000iterの山登り法を実装した。出力の見た目もseed=0に対する距離も思っていたより良くてウキウキで提出するとREが出て、悲しい気持ちになってしまった。(テストケースをファイルから読み込むコードのままだった事が原因だった)

2回目の提出 (~127分)

提出間隔が5分あるのでその間に自明な改善を考える。現時点では反時計回りのケースしか考慮していないが、それだと1000個あるタスクのうち約半分しか見ない事になって困るので、時計回りのケースに対しても試行を行って良い方を取るようにした。また、実行時間に余裕があったのでiter数を2e5に増やした。
提出を行った結果175万が取れて、この時点での10位になれた。

焼きなましの実装 (~160分)

現時点の実装は雑に山登り法を適用したのみなので、これを焼きなましに置き換える。実装してもスコアが上がらず困ったが、原因のバグ (焼きなましの遷移判定の直後に if(now_score > nex_score) が入っており、山登りの完全な劣化になっていた) を発見して解決した。178万点で21位。

焼きなましの調整, 二段階目の実装 (~215分)

iter数とスコアの関係を見た所、iter数が1e5になった辺りでスコアがほぼ改善しなくなる事が分かった。この方法だけだと限界がありそうなため、別の方針を考える。
今の手法は偏角によって配送タイミングに制約をかけているためそこに問題がありそうで、そうなると偏角に依存しない操作をしたくなる。そのため、偏角ベースの焼きなましで得られた解に対して一点挿入一転削除の山登りを実装する事にした。 挿入時にスコアが最も改善するような挿入位置の組を求める操作は累積minを使うと O(m) でできて、流石にここの O(m2) は許容できなさそうなので頑張って書いた。
集中力が切れてきた事もあって実装に時間がかかるため、5分に一度焼きなましのハイパラ調整を行って提出していた。186万点で17位。

終盤 (215分~)

二段階目の山登りが実装でき、194万で17位に戻ってきた。
残りは安定して点を稼ぎたかったため、一段階目と二段階目の実行時間のバランス調整や焼きなましの温度最適化を行い、5分に一回提出するようにした。
残り140秒で投げた最終提出がHighestで、最終的には195万点で19位となった。

反省

序盤の1時間半ぐらい全くアイデアが出なかったので反省。ただこの時にハズレ方針に手を付けて逃げられないみたいな事にならなかったのは悪くないし、結局当たりを引けたからOKかな・・・という気分。
2-optの高速化で勝負すると厳しいという事を判断して簡単な焼きなましに逃げられたのは良い判断じゃないかなぁと思う。焼きなましパートの必要以上の高速化を切って他部分の変更に時間を割けたのも良かった。
終盤の動きは適切っぽくて、自明な改善がなくなったタイミングで、可能な提出回数が少なくなるラスト数十分を手元でのスコア測定+ハイパラ調整での得点アップに割くムーブは正解そう?
あと記事を書いている時に気づいたんだけど、kick操作を全くしていないので局所最適から全然抜けられてなさそう。今回は雑にやって問題なかったけど、今後に備えてちゃんと設計ができるようになっておくべきかもしれない。

2022年度(令和4年度) 筑波大学情報学群情報科学類編入試験 受験記

はじめに

2022年度(令和4年度)の筑波大学情報学群情報科学類の編入試験を受験したので、試験の流れなどについて記録を残そうと思います。


試験内容と対策

数学/英語/情報 の3科目があり、恐らくそれぞれ100点満点で評価される。

数学

微積分と線形代数からそれぞれ一題出題される。微分方程式や数列、確率などは出題されない。

英語

TOEIC利用で、例年通りであれば730点満点らしい。
僕は十分な得点を取れていたので、これは対策しなくて問題なかった。

情報

プログラミングに関する問題が二題出題される。
細かいミスにさえ気をつければ十分な点が取れる難易度だと思う。


受験記

当日の流れ

当日は9時開場で9時30分集合、試験は10:00からの120分間だった。
単願が16人、情報科学類第一志望の併願が95人の合計111人が受験していた。情報メディア創成学類は単願5人、併願46人だった。
今年から情報科学類で物理を選択できなくなり、数学2問と情報基礎2問の大問4つを解く形式となった。
英語はTOEICもしくはTOEFL iBTで、自分は3年次に受験したTOEICのスコアシートを提出した。例年通りなら100点になると思う。
僕は問題2~4 (線形代数と情報基礎2つ) を完答して、問題1は冒頭1問のみを解き、他は部分点狙いで適当な解答を書いた。
ケアレスミスが無いと仮定すると270程度、問題1の部分点なしかつケアレスミスがあり採点が厳しかったとしても240点ぐらいは取れた感じの手応えだった。

試験問題

数学1 (微積分)

  • 極座標変換で解ける二重積分
  • 前問の答えを利用する二重積分
  • 二項係数で展開してから微分する証明問題

数学2 (線形代数)

  • 掃き出し法で線形独立なベクトルを求める
  • ベクトルの集合を部分空間の和で表して、部分空間とならない事を証明する問題

情報基礎1

  • ビンソート、分布数え上げソートに関する問題 (穴埋め、動作不備の指摘など)
  • 安定ソートの説明

情報基礎2

  • バーコードを2進で受け取って数値列に変換するコードに関する問題

2022年度(令和4年度) 山梨大学工学部コンピュータ理工学科 編入試験 受験記

はじめに

2022年度(令和4年度)の山梨大学工学部コンピュータ理工学科の編入試験を受験したので、試験の流れなどについて記録を残そうと思います。


試験内容と対策

調査書/面接/筆記試験(情報)の3つがあり、それぞれ50/50/400点がつけられている。

情報

プログラミング(アルゴリズムとデータ構造)、計算機アーキテクチャ、情報数学の3つの内から2つを選ぶ事になる。
プログラミングは普段コードを書いているなら問題なく解ける難易度で、ここは普通に解けば落とす事はないと思う。
計算機アーキテクチャと情報数学は(自分の)未履修な範囲から出題される事があったが、これも高専の授業内容を覚えていれば解ける難易度になっている。
大問の間に大きな難易度の差はないため、出題された問題ジャンルに合わせて好きな方を解けばよいと思う。

面接

普通の面接であり、形式や教員の態度などに特筆すべき点はない。
他が満点でも面接の内容次第で落とされる可能性があるらしいので、少し気を付けた方がよい気がする。

受験記

当日の流れ

当日は8時45分集合で、筆記試験は09:20から80分間だった。(試験時間は募集要項等には書かれていなかったが、例年80分らしい)
定員5人に対して出願者数は15人で、受験者数は14人だった。
筆記問題は下記の通りで、僕はハフマン符号を習っていなかったためプログラミングと計算機アーキテクチャを解いた。
特に難しい所はなかったため、細かいミスがなければ満点だと思う。
面接では志望動機ややりたい事、最近興味を持っている技術的な話題について聞かれた。

試験問題

プログラミング

  • 素数判定プログラムの穴埋め、計算量の記述 ( O(√N)と O(N) の2つについて)
  • 単方向連結リストのプログラムが与えられ、出力書き出しや動作説明
  • 部分和問題 ( O(N2N) のプログラムが与えられるため説明、O(NK) のアルゴリズムがどのような物か説明)

計算機アーキテクチャ

情報数学