valid,invalid

関心を持てる事柄について

ソフトウェアエンジニアとして求職活動中です

※ (2020-07-12 追記) 2020年6~7月の求職活動に伴う募集は終了しました。

令和2年6月1日より、ソフトウェアエンジニアとして"求職活動"を開始します。職務経歴書 (CV) を以下のページで公開していますので詳細はそちらをご覧いただければと思います*1興味をお持ちいただけた方はCVに記載のメールアドレスにご連絡いただけると嬉しいです*2

ohbarye.github.io

※英語版はこちらです: https://ohbarye.github.io/en/cv/ *3

※ (2020-06-03 追記) メールでの返信には~3日を要しています。Twitter DMは本記事公開以前から無法地帯となってしまっているため確認しておりません。

※ (2020-06-12 追記) 2020-06-12 21:00 JST 時点までに送られたメールについて、すべて一次回答はさせていただきました。もし漏れていましたらお手数ですが再度ご連絡いただけると幸いです。

本記事ではCVとは違った角度から、"柔和-くだけた-"表現でいくつか補足をしていきたいと思います。想定の8倍ぐらい長くなってしまったので「採用候補者としてコイツどうなんだ」と思って見に来られた方はCVだけ見れば大丈夫です。

*1:CVもブログに負けず長い…のですが、とある方から「情報の取捨選択は採用側で行うので多いほうがよい。見る人はちゃんと見るし、そういう会社こそマッチするのでは」とフィードバックいただきました。自身も採用担当やっていたときも確かに、情報量が多すぎて落としたことはないが少なすぎて落としたことはたくさんありました。

*2:やり取りがTwitter DMや各種媒体に分散するととても辛いということがわかってきました

*3:内容はほぼ同じつもりですがDeepL頼りの未添削の英文なので、日本語が読める方には日本語CVを推奨します

続きを読む

Now.sh (Vercel) で x-now-deployment-url が x-vercel-deployment-url になっていた

Now.sh (現Vercel)でホストしているアプリがいつの間にか落ちていた(index pageでいきなり500になっていた)ので直した。

goofi.now.sh

少しdebugしたところ、x-now-deployment-url というheaderがいつの間にか x-vercel-deployment-url にrenameされていたせいでリクエストするURLを正常に組み立てられずにいたようだった(これはstagingやproduction問わずdeploymentごとに値が変わるもので、HerokuでいうDyno metadataみたいなやつ)。他のheaderも軒並みnow=>vercelへrenameされているように見えた。

「何もしていないのに壊れた」というか破壊的な変更がいつの間にか入っていたという印象なのだがドキュメントに記述されていないうえに "x-vercel-deployment-url" で検索しても情報がまったく出てこない。

https://vercel.com/docs/v2/edge-network/headers#inlinecode

(2020-05-30 22:34 追記) 「以下に記載あるよ」と友人に教えてもらった。(彼は本番運用でこの問題に遭遇したらしい)

www.notion.so

カリキュラム標準J17でスキルの棚卸しをする

なんやかんやあり、伸ばしたいスキルを整理したり自分のスキルセットの棚卸しをしたりしていた。また、最近は有給消化期間で暇なのでふだんの業務から離れた領域の学習をしてみたいと思い、基礎分野であるデータ構造やアルゴリズムやコンピュータアーキテクチャについて学んだりしている。

そんな中、漠然と「ソフトウェアにもっと詳しくなりたい」「基礎を学びたい」と思いつつもそもそも基礎ってなんだっけ?という問いがあり、色々調べていたら"情報専門学科におけるカリキュラム標準"という便利そうなものを見つけた。自分で場当たり的に学習計画を立てるよりは既存の体系立てられたカリキュラムを参考にするほうが良いだろう、ということで"掘-ディグ-"ってみた。

情報専門学科におけるカリキュラム標準とは

日本には情報処理教育委員会という組織があって情報専門教育に関するあれこれをやっており、その活動の一つにカリキュラム標準の策定があるとのこと。

カリキュラム標準J07

カリキュラム標準J07-情報処理学会からそのまま引用する。

世界標準である米国IEEE/ACMのCC2001-CC2005を土台として、日本の情報専門教育の状況に対応した見直しを行い、コンピュータ科学(J07-CS) 情報システム(J07-IS) ソフトウェアエンジニアリング(J07-SE) コンピュータエンジニアリング(J07-CE) インフォメーションテクノロジ(J07-IT) の5つの領域と、広く情報について学ぶ内容を定めた一般情報処理教育GEについてまとめたカリキュラム標準です。幅広い情報教育分野のなかで、各知識領域について体系的に学んでいくべき 指針となるカリキュラム構成や最低限習得させるべき項目をコアと指定 しています。

計算機科学、と漠然と捉えていたものはJ07以降の教育カリキュラムでは5領域にわたるらしい。

また、ボリュームを変えずに5分割というイメージかと思いきや、総体のボリュームは増えていそう。その背景には「もともとの計算機科学のカリキュラムが数学など基礎分野に寄りすぎている」という指摘があったようだ。大学なので基礎を教えるのは当然な気もするが…。*1

とにかく、従来は計算機科学1領域がカリキュラムの対象だったが、社会の変化と計算機の爆発的な普及により、ACMIEEEが定めた大学カリキュラム案CC2005では5つの領域になった。

image

カリキュラム標準J07-情報処理学会 より。

この図はCC2205 Overviewを元にJ07用に改変したもので、各領域の分担範囲がわかる便利図(以下、分担範囲図と呼称する)だ。各領域の具体的な内容については後で見ていく。

カリキュラム標準J17

カリキュラム標準J17-情報処理学会からそのまま引用する。

J07の策定から10年が経過し、技術の内容が大きく変化したこともあり、今回全面的な見直しを行い、J17として公表することとした.

J17は、従来からの6カリキュラム標準に加えて、世の動きに合わせて情報セキュリティ、データサイエンスという発展中の対象領域についても、別立てに側面別カリキュラム標準をおく方針を立てている.ただし、現時点では、サイバーセキュリティに対する側面別カリキュラム標準J17-CyberSecurityの素案だけを提示する段階にある.

要はJ07はアップデートされ、現在ではJ17が運用されているということだった。

CyberSecuriry領域はまだ素案のみ、追加されたGEは基礎教養的な内容で既存の領域を薄くカバーするものなので本記事で掘り下げるのは元々の5領域のみとする。

各領域の担当

情報処理教育委員会に便利な説明があるので引用しながら見ていく。

CS (Computer Science)

CS は,情報の表現・蓄積・伝達・変換に関するアルゴリズム的プロセスを,理論・分析・設計・実現・評価の各面にわたって系統的に扱う領域である。この領域の根底にある問題意識は,「何が効率よく自動化できるか」である。

http://www.ipsj.or.jp/12kyoiku/acre/CS.html より

一般的に…かどうかは知らないが自分がイメージするコンピュータサイエンスはまさにこんな感じの領域だ。分担範囲図でもわかるように基礎領域であり、この分野の応用範囲は非常に多岐にわたる。

以下のトピックを扱い、掘り下げていく領域。

IS (Information System)

IS は,社会や組織の問題点を見つけ出し,組織の変革を行い,費用対便益の高い情報システムの開発・導入を創造的・効果的に実現するために必要となる,理論・技術・技量を幅広く扱う領域である。この領域の根底にある問題意識は,「いかにして最大の費用対便益をもたらすか」である。

http://www.ipsj.or.jp/12kyoiku/acre/IS.html より

突然"社会"とか"組織"とか出てきて応用感が強い。

学習領域もわリと応用感強いのだが、CSやSE領域の学習の土台の上で以下をやっていくらしい。

  • データ管理
  • 分析と設計
  • 組織における情報システムの役割
  • 情報システムを囲む環境
  • 多様な情報システムの事例理解
  • 情報システム開発の実践に必要な問題形成・モデリング・プロジェクト管理についての十分な量の実習
  • 立場や国を超えてのコミュニケーション能力・プレゼンテーション能力を得させるための十分な量と深さをもった学習

SE (Software Engineering)

SE は,CS およびソフトウェア工学 を基にし,「体系化された方法論および計量技法を用いて,ソフトウェアシステムを開発,運用および保守すること」を目的とする領域である。

http://www.ipsj.or.jp/12kyoiku/acre/SE.html より

クライアントワーク・受託開発における開発サイクル全般をカバーするような内容だ。産業界からの要請にめちゃめちゃ応えている感があるが、これもCSの基礎や数学の土台の上で学ぶもののようだ。

  • ソフトウェア技術者としての社会的責任の遂行と実践に必要となる,情報倫理・社会・法律・経済・安全に関する事項の学習
  • ソフトウェアシステムに関わる,要求分析,設計,検証・正当性確認,実現および保守に関する基礎的技術の学習
  • ソフトウェアシステム開発の実践に必要な,プロジェクト管理・プロダクト構成管理・プロセス管理・リスク管理・品質計量尺度に関する基礎的技術の学習
  • ソフトウェア開発プロジェクトに参加するために必要な,つぎの視点からのコミュニケーション能力養成
  • 提案作成,プレゼンテーション,聞き取りと分析
  • 計画,折衝,協調,技術・経済の両面からの意思決定,統括

シラバス的なものを読むとOOP、形式手法、アーキテクチャ設計、テスティング、CI/CDとかに触れていたりもする。

CE (Computer Engineering)

CE は,情報のプロセスを応用各面にわたって系統的に扱い,ハードウェアでの実現を目指す領域である. http://www.ipsj.or.jp/12kyoiku/acre/CE.html より

分担範囲図の中で唯一最下部をカバーするのがCE。基盤技術、システムプログラムに関する項目が並ぶ。

  • コンピュータシステム(論理設計,集積回路,コンピュータアーキテクチャ,電子回路,ディジタル回路,など)
  • 情報通信(信号処理,符号理論,情報ネットワーク,ディジタル通信,など)
  • コンピュータ応用(画像処理,音声処理,マルチメディア処理,データベース,人工知能,など)

かなり応用ぽい内容も含まれているじゃん、とは思った。

IT (Information Technology)

ITは,情報システムから,アプリケーション技術,そしてシステム基盤に至るまでの広い範囲にわたって,組織や個人の情報技術に関する広範なニーズに答えることを目指す領域である.

https://www.ipa.go.jp/files/000024071.pdf より

これはめちゃめちゃ広い…。

具体的な要素のプロット

さて、5領域のイメージがわかったところで、各5領域のBOK*2シラバスから具体的なトピックを抜粋し、分担範囲図にプロットしてみた。そうすることでより具体的なスキルマップとしての価値が生まれると考えたからだ。

結論から言うと、難しすぎて頓挫した。情報科学全般で扱う項目の数が多すぎる*3のですべてを抜き出すことはできず、また、複数領域にまたがる項目が多すぎて図上に正確にプロットできない。

いちおうできたのはこんな感じ。

f:id:ohbarye:20200524185933p:plain
カオスマップ感

要素が隣接していることや重なっていることや要素の大きさなどに全く意味はないので注意。

観察

当然ながら特定の技術要素や製品の名前などは浮かんでこない*4。大学で扱う基礎分野なので基礎分野なので数年〜十数年は廃れない内容が並んでいるはず。雑多ではあるがこの概観から「自分に足りないもの」を見つけてやっていけるかも。項目間の関係性のグラフこそが本当に欲しかったもののような気がしてきた。


CS領域≒情報科学という誤った認識を抱いていたため、扱う範囲の広さに面食らった。実際には各要素の背景や周辺には数学であったり電子工学であったり組織論であったりが存在するので、全てを修めるのは数年かけても難しそうだとわかってきた。


コミュニケーション・リーダーシップ・ネゴシエーションなどといったソフトスキルも情報科学の一分野(IS, IT, SE)に含まれていることもまた意外だった。コラボレーションや開発の手法も確かに大きくは変わらない…か。


区分けを見るとわかるようにScienceとEngineeringは密接に関わってはいるものの問題意識が異なるということが再確認できた。

自分と照らし合わせて

2020年5月現在の自分の経験・専門領域を重ねてみた。右上から中心にかけての黄色部分がそれ。

f:id:ohbarye:20200524190014p:plain
カオスマップがさらにヤクいことに。

調べながら「そうだろうな」とは思っていたのだけど、やはり過去7,8年の経験とそこで得た知識の大半はIT, IS, SEあたりとわかってきた。まぁITは広すぎるので上の表現でカバーしている範囲はちょっと盛り過ぎている気がするが…。

最近は学べば学ぶほど「ワイ、何も知らんな…」という気持ちになっていたのだが、業務や趣味の開発を通じて(それとは知らずとも)基礎領域の一部には足を突っ込んでいるとわかりちょっと安堵した面もある。


現在学んでいるデータ構造やアルゴリズムやコンピュータアーキテクチャ、そしてその周辺やさらに背景にある領域が、5領域全てに登場する基礎分野であると改めて再確認できたので引き続きやっていく気持ち、というか避けられない気持ちになった。

T字とかΠ型とかH型とかトライアングル型とかの分類から外れたこういうスキル棚卸しと分析もたまには良いかもしれない…と思ったけど棚卸しにはなってないな、これ。

*1:http://next49.hatenadiary.jp/entry/20080618/p1 に詳しい

*2:Body of Knowledgeのこと。PMBOKとか https://ja.wikipedia.org/wiki/%E7%9F%A5%E8%AD%98%E4%BD%93%E7%B3%BB

*3:とりわけIT領域は本当に広すぎる…これだけで全部カバーしているのではと思うほど。 http://www.acm.org/binaries/content/assets/education/it2017.pdf

*4:そういうのが見たい人はDeveloper Roadmap

2年半のエンジニアリングマネジャー経験から学んだこと

2017年6月〜2020年3月まで、Quipperという会社でEngineering Managerをやってみての振り返りです。

ここ数日こつこつと退職エントリを執筆していたのですがこのセクションが長くなりそうだったのと、単体で読まれても良さそうなので1エントリとして切り出しました。*1

マネジャーになった背景から失敗から学んだことから思いついたことをぐだぐだ書いていきますがはっきり言って個人の日記レベルなので野暮なツッコミはなしでお願いします。*2

というかこれは個人の日記ですよ〜。(ここまで防衛線)

*1:いっそ削ろうと思ったが、いま書かないと一生書けなくなりそうなので

*2:インターネットでマネジャーが失敗について語ると息巻いて攻撃する方を一定数見てきたのですが、せっかくの知見や経験の流通を妨げていて本当によくないと思っています

続きを読む

データ構造とアルゴリズムの基礎を100時間学習してみての所感

4月中は3週間ほど仕事をせず引きこもる時間があったので「データ構造とアルゴリズム」の基礎の学習に100時間ほど費やした。

f:id:ohbarye:20200511013957p:plain
あくまで目安としてSpreadsheetで学習時間を記録した。厳密ではない

学習においては量(時間)だけでなく質のほうが大事で、費やした時間で語るのはアンチパターンだと考えているが、「100時間でどれぐらい進捗するのか」のベンチマークとしてはわかりやすいと思うので参考までに書いておく。*1

インプット

データ構造とアルゴリズムをきちんと体系立てられた書籍やオンライン講義動画で学んだ。

あとは細かい記事を色々読んだり。

Coureraの "Algorithms Part I" に57時間、『みんなのデータ構造』に14時間ぐらい使っているので総合したら70時間強はインプットに費やしたことになる。

時間のほとんどはインプットに振ったにも関わらず全然足りない…と感じている。Courseraのアルゴリズムの基礎講座も半分だけだし、AtCoder水色になるために必要な知識群には半分も着手できていないし、データ構造とアルゴリズムに関連する数学の学習はほぼゼロに近い。無職を超えてさらなる無限の学習時間がほしい

アウトプット

「インプットした事柄の定着」と「理解度の測定」を目的とし、主に競技プログラミング、AIZU ONLINE JUDGE、LeetCodeを活用した。正確じゃないけど30時間ぐらいはやっていたはず。

期間中に計150問ぐらい解いて確かに目的に合致することも多くあったが、演習量も質もまだまだ不足を感じる。最近は"解ける問題を選んで解いている"感があって、なお良くない。

f:id:ohbarye:20200522004020p:plain
問いた問題数など (期間外も含む)

予想通りではあるが上述のインプット(初歩的なデータ構造と初歩的なアルゴリズムの学習)だけで劇的に競技プログラミングの成績が向上するわけではなかった。題意をつかむことや問題の考察、適切なアルゴリズムを当てはめて問題を解くにはそのための訓練が必要。それでもじわじわ伸びているとは感じており、AtCoderではようやく緑に昇格し、A~D問題は安定して解けるようになってきた。

所感

100時間やってこの程度か…という気持ちが強い。今の感覚だと400時間ぐらい、質を高めても250時間ぐらいは学習しないと一山を超えられない気がする*2

とはいえ、基礎(の一部)を学ぶことで問題の解説を読んで理解ができるようになったり、新しいアルゴリズムを学ぶときに必要となる土台を獲得出来てきたと感じる*3。 初歩的な知識があれば考察を必要としないような典型問題*4はわりとすらすら解けるようになってきた。前回のABC 168 D問題でBFSをさらっと書けたときは嬉しかった。

また、学んだデータ構造やアルゴリズムは本当に基礎的でありながら実用的であることがわかってきた。 ライブラリや言語やミドルウェアの内部実装を読むのにたまに便利で、時折、暇を見つけて以下のようなトピックを色々見ている。

今後

30代はこれまで避けてきた領域と本格的に向き合いたい*5と考えており、余暇でデータ構造とアルゴリズムの学習は継続するつもりだ。

基礎分野を学習するほどに「これまでよく知らずにやってこれたな…」と凹むことも多いが知らないのだから知るしかない。

とはいえ自分は個人的な学習において1つのことを数ヶ月単位で続けられない飽き性なので、5月は別の領域を学び、数週間後に戻ってくることにした。

次に再開するときにはCoursera, Algorithms Part 2でより基礎を深めつつ、実戦で使える引き出しをもう少し増やすための本も併読したい。

200時間学習した時との差分比較が楽しみだが、その頃には学習時間の計測に飽きていそうな気もする。

*1:せっかく記録したのだし…という気持ちもちょっとあるし量が質に転化するのを信じたい気持ちもある

*2:なんの定量性もないただの勘

*3:クラスカル法を学ぶ土台としてのUnion-Findとか、グラフを扱うアルゴリズムを学ぶ土台としてのDFS, BFSとか

*4:特にLeetCodeのEasy全般とMediumの一部でLinkedList, Stack, Heap, Priority Queue, HashMap, BFS, DFS, Tree, BT, BST, Sort, Binary searchあたりを扱うやつ

*5:大学では人文系を専攻し、プログラマとしてのキャリアでは長らく場当たり的に学習を続けてきたツケを払うターン

『CPUの創りかた』でCPUの設計と動作原理を学んだ

コンピュータシステムの学習の一環として『コンピュータシステムの理論と実装』 (通称Nand to Tetris project) を進めているのだが、Nand to Tetrisの課題ではハードウェア記述言語を使ってハードウェアをコードとして表現し、あくまでエミュレータ上で回路を実行するので現実のハードウェアに関するイメージがリアルに湧かなかった。

それでも学習には大いに役立っているのだが副読本として『CPUの創りかた』を読んだ。工作はしていないのであしからず。

CPUの創りかた

CPUの創りかた

実際にパーツを用いながらCPUを構築していくマジモンの電子工作本なのでテスター(電圧を測定するやつ)や部品の準備から始めていく。制作のために実際の製品やメーカーの名前が挙がるのでコンピューターを支えている企業に思いを馳せることができる。

前半は電子工作に関する記述が中心なのでソフトウェアエンジニアがCPUの動作原理や設計について詳しく知りたい場合はChapter 6以降を中心に読むと良さそうだ。機械語の知識、CPUのbit数とは何か(演算やデータ移動の単位が決定する)、CPUの命令フォーマットの設計、ジャンプ命令の実装方法、フリップフロップ、加算器、命令デコーダなど専門的な内容が盛りだくさんではあるが軽妙な文体なのでわりとサクサク読める。

本書の最後のほうで「実際にはこのように細かい部品を組み合わせてCPUを設計・実装することは現代ではほぼない*1とハッキリ言っているが、あとがきにある「ブラックボックスを1つ減らす」のはとても価値があるし何より面白い。


もともと工作する気はなかったのだけど、実際に組んでみた方々を見ていたらやりたくなってきたのでそのうちやるかもしれない。

www.youtube.com

*1:ロジックをプログラムで制御できる[CPLD https://ja.wikipedia.org/wiki/CPLD]を使う

Courseraで"Algorithms, Part I"を修了した

アルゴリズムの学習の一環としてCourseraの "Algorithms, Part I" を完了した。

www.coursera.org

先日アルゴリズムに関する学習教材を探していた折、同講座に関する満足の声を見かけたのでやってみることにした。(英語のレビューは上記ページに載っている)

時間はかかったが全課題を及第点以上で完了できた!!

"Algorithms, Part I" とは何か

Princeton大学がCourseraで公開している、アルゴリズムに関する講座である。Part I, IIの2つの講座があり、Part Iでは基本的なデータ構造、ソート、および検索アルゴリズムを扱う。本記事ではPart Iの話をする。*1

コースの説明には "This course covers the essential information that every serious programmer needs to know" という強い言葉が書かれており、今すぐやれと煽られている気がしてくる。

この講座の公開は2012年頃とのことだが実に基礎的な領域を扱っているので教材としての価値は2020年でも全く衰えていなさそうだ。むしろ半世紀を超えてなお現役だったりするアルゴリズムたちを学ぶことで、廃れることなく有用な知識とは何であるかということを改めて考えさせられる。

無料

この講座は動画の視聴〜課題の採点まですべて無料。ただし修了証明書の発行はなし。

満足度がすごく高いのでお金を払いたいぐらいなのだが…。

講師

動画の講師はRobert Sedgewick先生。講座内容はセジウィック本(英語圏ではアルゴリズム解説の定番書とのこと。600ページ超のなかなか重そうなやつ)をベースにしている。

英語字幕は全編にわたって存在する。ちなみに日本語字幕は一部講座のみにしか存在しないのであてにしないほうがよい。

ボリューム

公式には "Approx. 53 hours to complete" と書かれている。自分の場合は57.5時間かかった。

「動画を見る -> 課題を解く」

のシンプルな構成を素直にやったわけではなく、

「動画を見る -> 英語or内容が理解できなければ巻き戻す -> 理解できた内容をノートに書く -> 課題を解く」

のように丁寧に学習した。課題は平均して6.5時間ぐらいで終えたと思う。((各週に用意された課題1つ解く目安が8時間とあるので課題だけでも8 * 5 = 40時間かかる計算のようだ))

私とJavaIntelliJ

課題はすべてJavaで提出する。

5年以上Javaから離れて過ごしてきたので不安だったが、IntelliJ IDEA Community Editionとプロジェクトファイルが提供されるので環境構築で躓くことはなかった。format on saveとか、findbug on compileとかも入っていた。

課題を解く上で要求されるJava自体の知識というのはほとんどなく、条件分岐やオブジェクト指向など一般的なプログラミングの知識があればあとはJavaの記法を調べてコードに落とし込むだけだった(まぁそれでいらいらすることもあるのだが…)。実装対象のクラス名やpublic APIは指示があるし(従わないと採点不可になる)、IteratorやComparetorなどで込み入った実装をする際には記法のサンプルが提示されている。

動画内でのセジウィック先生の解説もJavaベースだが、こちらもJavaの練度が理解を大きく左右するような箇所は殆どなかったと思う。

良かった点

実践的で頭を使う課題

Week 6を除きすべての週に課題が用意されており、これが非常に良かった。解説したアルゴリズムをそのまま記述しろというようなお勉強ぽい内容は少なく、「現実世界ではこのような問題を解くのにアルゴリズムが使われるぞ」というのを実感できる内容が多かった。

また、APIデザインを変えずに内部実装の工夫で高速化や効率化を測る工夫が求められるのも良い。現実でもそういうシーンがしばしばある、と語っておられた。

ナイーブな実装では要求するパフォーマンスを満たせ無いことが多い。採点では何よりも正しく実装することへの配点が大きいものの、パフォーマンスやメモリ使用量に関するペナルティでもしばしば減点される。

ちなみに課題採点は完全に自動化されておりいつでも何度でも提出ができるし、ローカルで実行可能なテストデータも提供される。

(どんなに質の高い講義動画であってもずっとPCの前で話を聞くだけだと眠くなってしまうので手を動かす課題のほうが面白いというのもある)

解説が丁寧

科学的なパフォーマンスの解析に焦点をあてる、とコースの説明に書いてあるのだが予想以上に丁寧だった。

ざっくりとした計算量オーダーを見積もって終わるのではなく最悪実行時間、償却実行時間、期待実行時間それぞれについて時間を割いているので知っているつもりのアルゴリズムの違う側面が見えたりする。

応用事例に広く触れている

学ぶ内容は基礎だが、各種データ構造とアルゴリズムの応用事例に触れていることが多く、全体的に応用への強い意識を感じる。

たとえばStackの利用シーンとしてJVM, エディタのUndo, ブラウザのバックボタン, コンパイラにおける関数呼び出しの管理を挙げたり、Priority QueueについてはイベントドリブンなシミュレーションやゲームAIの話になったり。

全6週をおさらい

学んだ内容を軽くおさらい。

解法までは書いていないが課題についても触れるので一切の事前情報なしに挑戦したい人は一番下の「まとめ」まで飛ばしてほしい。

Week 1: Union-Find, アルゴリズムの解析

前半ではUnion-Findを扱う。要素のグループ分けを木構造で管理するデータ構造です…みたいなことを言われてもフーンという感じだが、この講座では「Quick Find -> Quick Union -> 改良版Quick Union」の順に実装を詳解し、アルゴリズムの問題点の指摘から計算量の劇的な改善に至るまでを俯瞰する。

「コンピュータの速度がいかに早くなろうともアルゴリズムの強力さは一切失われず、それどころか、扱うデータや人々の性能への期待が増え続けるのでより重要にさえなっていく…」というようなことをSedgewick先生がたびたび言うのだが、冒頭からそれを言葉でなく心で理解できるようにしている講座設計が非常に良かった。

課題

講義で解説したUnion-Findはライブラリとして提供されるので、それを利用してpercolationを扱う課題。*2

f:id:ohbarye:20200510203037p:plain
https://coursera.cs.princeton.edu/algs4/assignments/percolation/specification.php より引用

盤面にランダムに穴を空けていったとき、何回の操作でpercolationが発生するかをモンテカルロ法で求める。

Week 2: Stack, Queue, 基礎的なソートアルゴリズム

StackとQueueという基本的なデータ構造の解説。

『みんなのデータ構造』でデータ構造の基礎を学んだ - valid,invalidにも書いたのだが、基本的なデータ構造のインタフェースと性能を知るだけでなく内部実装の違いを学べるのが面白い。

課題

双方向キューのDequeとRandomizedDequeの実装を行う。

インタフェースを理解したうえでリストで実装するか、配列で実装するかなどを考慮する。

また、配列で実装する場合には性能要件を満たすためにresizeの実装を工夫する必要がある。

Week 3: Mergesort, Quicksort

主要なプログラミングの内部でも多く使われているマージソートクイックソートに関しては詳細な解説があった。

重複キーが存在するケースの性能や安定ソートの問題に触れたり、データ型の定義とソート処理ロジックの分離(ソート条件ごとのComparatorを用意する)など。

クイックソートの応用で重複するデータを検査せずに分割を完了することができるDijkstra's 3-way partitioningなど、発展的な内容も一部あった。

課題

平面内にあるn個の点から4つ以上の点を接続するすべての線分を見つける課題。パターン認識の基礎。

f:id:ohbarye:20200510203157p:plain
https://coursera.cs.princeton.edu/algs4/assignments/collinear/specification.php より引用

まずBruto forceで解いて、次にソートを上手く利用して高速化するよう促される。

安定ソートの問題に直面する。

Week 4: Priority Queue, Symbol Tableの基礎

Stack, Queueと違い、追加順ではなく最小または最大の要素をremoveするPriority Queueを扱う。内部実装の解説でヒープについても触れる。

ヒープの要素が整列される様子がアニメーションで解説されるのだが、Sedgewick先生がピーターの法則に言及していたのが面白かった。

課題

スライドパズルをPriority Queueを使って解く。

f:id:ohbarye:20200510203254p:plain
https://coursera.cs.princeton.edu/algs4/assignments/8puzzle/specification.php より引用

これはなかなか難しかった。基本的には幅優先探索なのだが、各盤面がどれだけゴールに近いかを評価して高速化を図るのが工夫のしどころ。

このように評価関数(ヒューリスティック関数という)を導入するA*アルゴリズム自体は知っていたのだが、ほんの少し関数をいじるだけで実行速度が段違いになるというのは手を動かさないとなかなかイメージできなかったので良い演習になった。

Week 5: Balanced Search Tree, Geometric Applications of BSTs

テーマはBST全般だが、この講座の白眉であるRobert Sedgewick先生が研究していた赤黒木の解説が遂に来る。

実際、赤黒木の解説は力が入っていると感じた。他の動画はたいてい10~20分なのに赤黒木の説明動画だけ35分もある(確かに木の操作とか説明に時間がかかる内容ではあるが)。

Sedgewick先生が赤黒木の論文を書いたのが1979年、大学の講義で赤黒木を扱う中で2007年にさらに改良された実装を見つけたという話と、"there are simple algorithms still out there waiting to be discovered and this is one of them that we're going to talk about." という言葉はグッときた。

課題

平面上で最も近い点を求めたり、図形の中にどの点が含まれているかを検出する。

f:id:ohbarye:20200510203505p:plain
https://coursera.cs.princeton.edu/algs4/assignments/kdtree/specification.php より引用

この課題ではKd-treeというデータ構造を用いる。このデータ構造は講義の動画を見るだけではあまり理解できなかったのだが、実際に課題でアルゴリズムを書く中でようやく理解できた。

また、一見すると木構造とは関係なさそうな平面や立体上の問題も木構造に落とし込むことで強力なアルゴリズムを活かすことができるという学びもあった。

Week 6: Hash Table, Symbol Tableの応用

最終週の主な内容はHash Table。衝突回避の方法としてSeparate chainingとLinear probingの両方を学んだり、Hash TableとBSTのどちらを使うべきかを考察したり、脆弱なハッシュ関数が起こした過去の問題などについても触れた。

最後のSymbol Tableの応用では現実のアプリケーションとの関連を解説。ここはこれまでの内容を深堀りするのではなく事例紹介という感じ。

最終週の課題はなくてちょっと寂しかった。

まとめ

アルゴリズムの基礎をしっかり学びたい」という自分の要求に照らし合わせると素晴らしい教材だった。

すでに学んだ経験がある人の復習に適しているかはわからないが、理解度を試すためにプログラミング課題に挑戦してみるのは面白いと思う。

真面目にやると50時間以上かかるボリュームがあるので怖気づくが、「コンピュータサイエンスを専攻した人はこのレベルの内容を学部4年間で修了している」と思えば追いつくには時間をかけるしかない。短期間で知識を身に付けるには単に量をこなすだけではなく質も大事なのでこうした有用な教材に積極的に挑戦していきたい。

より発展的な内容にフォーカスする "Algorithms, Part II" にはまだ着手していないが2020年内には終えるぞ!!

*1:Part IIでは、グラフおよび文字列処理アルゴリズムに焦点を当てているようす

*2:percolationは直訳すると浸透だがあくまで抽象的なモデル。図だと上から下に水が流れる様子だったりするが、通電などをイメージしてもよいかもしれない。