こんにちは、エンジニア、業務委託の深山 @kenzan100 です。
突然ですが、皆さんは「アルゴリズム」と言われて何を想像しますか?
アルゴリズムというと、とっつきにくい技術分野/難しそう、という印象があるかと思います。しかし、「期待する成果を出すための、一連の手順に沿ったプロセス」という意味であれば、私たちは無意識のうちに様々なアルゴリズムを使いながら生活していると言えます。
会社までの通勤経路アルゴリズム、目玉焼きを上手に焼くアルゴリズム、歯磨きをするアルゴリズム...
もしかしたらエンジニアであっても、アルゴリズムを意識しながらコードを書く機会はそう多くないのかもしれません。ライブラリやフレームワークが充実している言語であればなおさらです。
アルゴリズムを学ぶ意義
それでも、私はアルゴリズムを学ぶ意義は大きいと思います。
私にとっての最大のモチベーションは、「利用者から開発者へ、一段技術を深堀りできるから」というものです。 Rubyでいえば [3,1,2,4].sort
が [1,2,3,4]
を返すことを理解しているのは「利用者の視点」です。
利用者の視点で満足することなく、「Rubyが sort
をどう処理しているのか」を知ることで、Ruby開発者の視点に(局所的ではありますが)おりていくことができます。
こういった内部実装の理解が進むと、さまざまな技術に主体的に関わることができます。それがエンジニアとしての自信につながります。「好奇心旺盛でい続けること」と置き換えても良いかもしれません。この姿勢は、(アルゴリズムに限らず)エンジニアとして成長し続けるために必須のものだと思います。
アルゴリズム勉強会 @クラウドワークス
私がこの二ヶ月間働いていたクラウドワークスではそんな好奇心旺盛なエンジニアが集い、アルゴリズム勉強会が開催されました。
この勉強会では、 Udi Manberという方が書いた Introduction to Algorithms をテキストに使いました。別の著者で 同名の本があり(CLRSという俗称がついています)、そちらが一般的なのですが、今回はあえてマイナーな方を選びました。
その理由は、この本が「数学的帰納法(Mathematical Induction)というただ一つのアプローチを用いて、ゼロベースでアルゴリズムを考える思考を教えている」からです。
モチベーションを維持するために、こういった「シンプルなアプローチから、多くの方法を導出できるテキスト」は貴重だと思います。
進め方
本勉強会の進め方ですが、メインの章である数学的帰納法を用いて例題を解いていく第5章(30ページ弱)を持ち回りで読むことにしました。
参加者の数こそ最初は安定しませんでしたが、徐々に常連メンバーが定着し、一月の頭からはじまって2月の末で無事章の最後まで行き着くことができました。
今思うと
- マイナーなテキスト
- 業務に直結するわけではないトピック
- さらにテキストが英語
というかなりのハードモードな勉強会でしたが、きちんと最後まで開催できました。あらためて参加していただけた皆様に感謝申し上げます。
常連さん
ハードモードな勉強会 開催Tips
せっかくなので、こういったハードモードな勉強会を開催するtipsをご紹介したいと思います。
1. 進行方法を決めるリハーサルを、事前に少人数で行う
本勉強会をやりたいと打ち明けたとき、所属したチーム内できっちりリハーサルをしました。そこで背景やテキスト概略をお話しし、良い塩梅の分量が設定できました。
どんな類の勉強でも、テキスト一冊となると膨大な量になります。なぁなぁで告知してしまうと、やりたかったことができないまま尻すぼみになってしまうリスクがあります(ハードモードであればなおさら)。
社内告知をする前に、必ず意思をもった数人でリハーサルをやるべきだと思います。
2. 自由参加/ランチ時間で開催する
これは言わずもがなですが、ハードモードなトピックを強制参加にすることは、百害あって一利なしです。あくまで独学の延長線上であることをわきまえて、主催したい人の他にもう一人でも常連が生まれれば成功、と定義すべきだと思います。
特に大事な視点は、「そのトピックは業務に直結するか?(得た知識が一ヶ月と経たずに「使えた!」となるか)」ということでしょう。これへの答えが Noであれば、その勉強会はハードモードな可能性が大きいです。
社内で声をかけられる母数がそもそも少なそうであれば、各種イベントサイトを使って、どの程度のニーズがあるものなのか試しに告知してみるのも良いかと思います。(都内であれば、最近は https://eventdots.jp/ が勉強会用イベントスペースを開放していて便利です)
3. 「各自で事前に例題を解いてくる」など、明確で多様性がある宿題を設定する
これは、もっとも大切なものかもしれません。勉強会を開催する上で、「アクティブな参加者」と「受身な参加者」は必ず生まれます。
そのときに、アクティブな参加者が勉強会に貢献する方法として、宿題はとても大事なものです。その点、本テキストは各小見出しごとに例題があり、解き方は各自工夫できるので、良い宿題設定ができたと思います。
終わってみれば、お互いが書いてきたコードを披露し合うその時間がもっとも有意義だったかもしれません(テキストはあくまでガイドライン程度)。
例題のご紹介
それでは最後に、勉強会の成果からいくつか参加者の解答を紹介したいと思います。
どの問題を紹介しようか迷ったのですが、一番回答に多様性があった 第5章 第5節 の「セレブリティ問題」というものをご紹介します。
これは、
向きを持ったグラフ(Twitterのソーシャルグラフのようなものをイメージしてください)があったときに、「その人自身は誰もフォローしていないが、グラフ上の全ての人がその人をフォローしている」という人(=セレブリティ)が存在するか。存在する場合はそのセレブリティが誰か答えよ。
という問題です。
実際のTwitterだと 日本人アカウントでフォロー数0で有名な方は つぶやきシローさん とかみたいですね。Twitter上の全アカウントが彼をフォローしている訳ではないので、この問題におけるセレブリティには該当しません。すみません。
下図がサンプルインプットだとすると、Cさんがセレブリティなので、それを見つけるプログラムを書いてください、ということですね。
皆さんなら、どう考えるでしょうか。 過去に似た様な問題を考えたことがある方ならともかく、なかなか一から考えるのは難しいと思いませんか。
このときに、数学的帰納法を使うと「考え始めるとっかかりができる」というのが、本勉強会テキストの趣旨です。
数学的帰納法というのは、問題の構造を保ったまま、問題が扱うインプットのサイズを減らしていくことで、再帰的にアルゴリズムをデザインする考え方です(この本ではそう扱います)。
今回のサンプルインプットですと、A~Dの四人をいっぺんに考えるのは難しいので、AさんとBさんの二人だけだったらどうなるか考えてみましょう、ということですね。
全てを書くと文章が長くなってしまうので、中身は割愛します。気になる方は、ぜひテキストの 5.5 Celebrity Problemを読んでみてください。
回答コード
さて、お待ちかねの参加者の回答コードはこちら。
- 深山(Ruby) https://github.com/kenzan100/CS101_Ruby/blob/master/manber/5.5.rb
- 沢田(Ruby) https://gist.github.com/cesare/0afa3fe99441f79bb19c
- 小屋(Go) https://gist.github.com/yosu/dd29e28bebff5d1833fd
面白いのは、同じRubyであっても、問題のデータ構造への落とし込み方が全く違うことだったりします。他にも、Haskellでの回答は回答者の中からよく出ました。再帰と相性が良いからでしょうか。
ここまで、二ヶ月間にわたって開催したアルゴリズム勉強会をまとめて、「ハードモードな勉強会の開催tips」と勉強会の中身をご紹介しました。
みなさんの好奇心を少しでも刺激できていれば幸いです。
クラウドソーシングで有名なクラウドワークスでは、好奇心爆発のハードコアなエンジニアの方を絶賛募集中です。 ご興味ある方はぜひ遊びにいらしてください。