PC初心者が東京大学理学部情報科学科を卒業した話

※ 2019年3月31日に公開した記事ですが、授業の雰囲気などを参考にしてくださる方がいらっしゃったようなので、3年前半の授業内容を中心に少し追記しました(2019年4月17日)。

はじめに

先日卒業式を終え、本日3月31日をもって東京大学理学部情報科学科を卒業します。
情報科学科というと中高時代からPCをいじっている人が行くところというイメージがあると思うので(実際そういう人は多いですが)、プログラミング初心者の人がなんとかやっていった記録を残しておこうと思います。

TL;DR

  • 始めは厳しいが、カリキュラムについていけば困らない程度のプログラミング能力は身につく
  • 周りに強い人が多いので初学者にとってはチート環境
  • プログラミング能力だけでなく、情報科学の基礎的な理論も身につく
  • 競技プログラミングおすすめ

専攻を決めるまで

東京大学では、2年前半までは教養の授業を受け、2年後半から学部・学科を選択するようになっています。

自分はプログラミングどころかパソコンもそれほど使っているタイプではなかったのですが、理論的なことを考えるのが好きで、数学科よりは現実に近そうという理由で情報科学科を選択しました。

雰囲気

全体として優秀なだけでなく、学問に対して真っ直ぐで尊敬できる人が多いです。
授業で出される課題はかなり多いのですが、とりあえず丸写しするというような雰囲気が全く無く、みんな一緒に苦しみながら教え合うという雰囲気がすごく好きでした。
「地下」と呼ばれている学生控室があり(文字通り地下にある)、大変な課題の〆切の前の日には学科民と泊まって徹夜で終わらせていたのが懐かしいです。
こういった環境から、実力は付きやすいと思います。

また、全体的に自由な雰囲気で、授業の出席は基本的にありません(成績はテスト、課題提出が主)。
そのため、自分の興味のある分野について好きなことをしている人も多いです。

2年後半

週に2回情報科学基礎実験という授業があり、そこでプログラミング言語の基礎を学びます。
半年という期間のわりにC言語、Scheme(関数型言語)、アセンブリ、データ構造・アルゴリズムの実装と内容が多いです。
同期はラクにこなしている人が多かったですが、「コンパイル」どころか「ターミナル」や「エディタ」といった単語もわからなかった自分にとってはかなりキツかったです。
同期との知識量の差という意味では、一番始めのこの授業が一番大変だったかもしれません。
C言語の授業が3週間ほどで終わって唖然としたことを覚えています。

ポインタがよくわからなかったので、ありそうなシンタックスをコンパイルエラーがなくなるまで全探索するという手法でコーディングしていました。
この理解のままC言語でデータ構造やアルゴリズムを実装するのがかなり鬼でしたが、気合いでなんとか課題をすべて終わらせました。

他学科の授業を取らなければならず、数学科の授業を取っている同期も多かったです。 数学を落ち着いて勉強できる機会もあまりないため、たくさんとっておけばよかったと後悔しています。

3年前半

情報科学科の中で授業や課題が一番多い学期です。
実験と呼ばれる、課題が中心の授業が3つあります。

  • ハードウェア実験
    回路の授業です。
    Verilog(ハードウェア記述言語)を用いてハードウェアの実装をするのが主でした。
    自分は、FADD(浮動小数点の足し算)を実装する課題のデバッグで苦労した覚えがあります。

  • システムプログラミング実験
    Linuxの基礎について学ぶ授業です。
    前半はLinuxのシステムコールが中心で、TCP/IP通信のサーバーとクライアントを実装したり、shellを実装したりしました。
    後半はベアメタルプログラミングという、OSがほぼない状態でのプログラミングをやりました。 Linux Kernelのソースコードを少しいじったりもした気がします。

  • 関数・論理型プログラミング実験
    OCamlを使って関数型言語の概念を習得することが中心の授業でした。 モナドとかの概念もやりました。
    Prologも少し触りました。 そういえばPrologの処理系を作っている同期がいた気がします。
    最後に余興(?)としてOCamlでオセロAIを実装する課題があり、面白かったです。

1つ1つの課題は大変ですが、TAの方のサポートも厚いので大学にしっかり行って真面目にこなしていけばどうにかなると思います。
なお、自分はシステムプログラミング実験は次の年に回すという選択をしました(単位落としました)(Cのポインタがわかっていない人が受ける授業ではなかった…)。

これ以外に、座学で情報科学の各分野の理論について学びます。

この頃まではバイトなどで忙しく、勉強にあまり時間を割いていなかったのが後悔点です……

3年夏休み

プログラミングが多少できるようになったので、Web系のベンチャーでインターンしました。 Webの基本的な仕組みやGitHubを利用したチーム開発などについて学べました。

あと個人的な理由で1ヶ月中国に行っていました。

3年後半

CPU実験という名物授業があります。 自作のCPUをFPGA上で動かして、自作のコンパイラでコンパイルしたレイトレーシングを動かすというものです。 班によってかなりモチベーションに差があり、自分たちはあまりモチベーションがなかったので課題要件を満たして終わらせましたが、自作OSを動かした同期の記事がバズったりしていました。

並列して、OCamlのインタプリタを実装するプロセッサ・コンパイラ実験という授業もありました。
座学は、3年前半の発展的な内容のものが多かったです。

このころ自分は将棋ソフトを作るのにハマっていました。
学科同期の@xuzijian629を誘って大会に出たりしていました(ここでチームGirigiriが発足しました)。
プログラミング技術がまだまだで、機械学習に対する知識も無だったため大したものは作れませんでしたが、楽しかったです(GitHubレポジトリ、Rustで書きました)。 時間があったらちゃんと作り直したいなあ、、

4年前半

授業はそれほど忙しくなかったので、ちょこちょこインターンに行ったりしていました。

演習3という研究室を3つ(それぞれ1ヶ月ほど)回って、簡単な研究をするという授業がありました。
暗号・離散数学・機械学習の3つの研究室を回り、それぞれ

  • RC4暗号
  • Weisfeiler-Lehman Graph Kernels
  • AlphaZero

に関する研究もどきをやりました。 人生で初めて、英語の論文を真面目に読んで考える経験をしました。

@xuzijian629に誘われて、@ogingin6と一緒にチームGirigiriでICPCの国内予選に参加しました。
ICPCというのは競技プログラミングの大学対抗のチーム戦で、直前期はかなり練習しましたが東大内予選が厳しく予選突破できませんでした(参加記)。
この時期競プロにかなりハマっていましたが、国内予選が終わってから一旦熱が冷めました。

そういえば、1年前にサボった「システムプログラミング実験」の単位を取りました。
プログラミング能力が上がっていたので1年前ほどの苦労はしませんでした(それでも時間は取られたので院試の勉強が……)。
感覚的にはこの頃に、基礎的な知識やプログラミング能力についてやっと周りの平均レベルについていけるようになったかなあという感じでした。

4年夏休み

院試がありました。
それなりに高い点数が取れて、倍率が高かったらしい希望の研究室に入れました。
情報科学をそれなりに身につけられたという自信に繋がりました。

院試が終わってからはずっとWeb系のメガベンチャーでインターンしてました。 普通に業務の内容をやらせてもらってそれなりに進捗が出せたので、将来困ってもWeb系で雇ってもらえるという自信を得ました。
一方、今はより技術的にチャレンジングなことに挑戦したいと思うようになりました。

4年後半

夏のICPC国内予選の関係で、バルセロナで行われた競技プログラミングの強化合宿に参加できました。
世界各国から集まった強い競プロerを目にして競プロにハマりました(2回目)。
Codeforcesに登録して、AtCoderと合わせて週に3-4回コンテストに参加する生活を送りました。

機械学習の研究室に配属されて、卒業論文を書きました。
卒論については、少し前にtwitterでバズっていた研究室同期の記事を読むと雰囲気がわかると思います。
自分はここまで何度もテーマを変えることはしませんでしたが、やはりかなり大変でした。
テーマは、NP困難問題に対する機械学習を用いたヒューリスティクスで、強化学習とGraph Convolutional Networksを勉強して新手法を実装しました。
特に苦労したのは以下の点です。

  • テーマ決め
  • 先輩や教授に自分のテーマについて詳しい方がいなかったため、内容面に関するアドバイスを全く受けられなかった
  • 元にした論文の詳細なデータやソースコードが公開されなかった、その他怪しい部分がいくつかあった
  • 提出締め切り1週間半前にインフルエンザにかかって1週間寝込んだ

実用的なアドバイスとして、特に卒論は研究室に詳しい人がいるテーマを選ぶのがいいかもしれません。
また、元にする論文のソースコードが公開されているかは最初に確認した方が良いです。再現の難しいものについては特に。。

これから

修士2年間も卒論と同じ研究室で研究します。
とりあえず5月締切の国際学会に卒論の内容を提出する予定です。

7月に最後のICPC国内予選(参加資格がM1までなため)があります。
そこで予選を突破することが当面の目標で、日々競技プログラミングを精進する生活を送っています。

最後に

特にターゲットを決めずにダラダラ書いてしまったのですが、学科に興味を持った東大1,2年生は学科のホームページを見てみるといいでしょう(最近進振りの底点が爆上がりしているので気をつけてください……)。

競技プログラミングに興味を持った人は、AtCoderというサイトに登録してAtCoder Beginners Selectionをやってみるといいかもしれません。

最後になりますが、学科の同期には本当に感謝です。みなさんがいなかったら今の自分はないです。これからもよろしくお願いします。