ビジネススクールで受講した「テクノベート・シンキング」の学びを全12回でまとめるシリーズ、その5。
第3回の授業テーマは「アルゴリズム」。事前課題では、バブルソートのアルゴリズムをフローチャートに表し、Scratchで実装するというものだった。
正直に言うと、「バブルソート」という名前は聞いたことがあったが、自分でフローチャートを描いてプログラムに落とすのは初めて。IT畑で長くやってきた私でも、アルゴリズムを「自分の手で」組み立てるという経験は意外と少なかった。インフラの仕事では、ソートはデータベースやライブラリが勝手にやってくれるからだ。
なぜ「もっとも非効率なソート」をわざわざ学ぶのか
バブルソートは、隣り合う2つの数字を比較して、順番が逆なら入れ替える──これを繰り返すだけのソートアルゴリズム。もっともシンプルで、もっとも非効率なソートとも言われる。
実務で直接バブルソートを使うことはほぼない。データベースのORDER BYやPythonのsorted()関数の裏側では、もっと高速なソートアルゴリズムが使われている。では、なぜわざわざ学ぶのか。
答えは、「シンプルだからこそ、アルゴリズムの構造がむき出しになる」からだ。ループ・条件分岐・変数管理というプログラミングの基本要素が全部入っている。余計な複雑さがないから、アルゴリズムの設計思想そのものと向き合える。この課題は、まさにそれを体感するためのものだった。
二重ループという構造──外側が「何周するか」、内側が「何を比較するか」
バブルソートの構造は、外側ループと内側ループの二重ループだ。
外側ループは「全体を何周するか」を制御する。1周するたびに、一番小さい(または大きい)値が確定位置に移動する。内側ループは「隣同士を比較して入れ替える」処理を繰り返す。周回ごとに比較範囲が狭くなっていく──すでに確定した部分は見なくていいからだ。
フローチャートに落とすと、二重ループと条件分岐だけで構成される非常にきれいな構造になる。「アルゴリズムとは何か」を視覚的に理解するには最適な題材だと思った。
ただ、「きれい」と「簡単」は別物だ。二重ループということは、2つのインデックス(今何周目か、今何番目を見ているか)を同時に管理する必要がある。外側ループが1周進むごとに内側ループの範囲が変わる。この「範囲が動く」感覚が、フローチャートを描く段階では理解できても、実際にプログラムに落とす段階で混乱の原因になった。
たった1つのフラグで効率が劇的に変わる──基本版と改良版
課題ではまず基本版を作り、次に改良版を作った。この2つを並べたときの気づきが、この回で最も大きな学びだった。
基本版は愚直だ。データがすでに並べ替え済みであっても、律儀に全周回を回りきる。「もうソートは終わっているのに、まだ比較を続けている」状態が発生する。
改良版では、ここに「入替有りフラグ」を1つ追加した。内側ループの中で1回も入れ替えが発生しなかったら、「もうソート完了」と判断してループを早期終了するロジックだ。
やっていることの本質は同じ──隣同士を比較して入れ替えるだけ。でもフラグ1つの工夫で、最良ケースの効率が劇的に改善される。すでに並べ替え済みのデータに対して、基本版が律儀に全比較を行うのに対し、改良版は1周目で「入れ替えゼロ」を検知して即終了できる。
授業で計算量の話は何度も出てきていたが、正直言って教科書の説明だけではピンとこなかった。自分でフローチャートを2つ並べて「ここが違うとこれだけ変わるのか」と体感したことで、効率の差が数式ではなく実感として腹に落ちた。
「フローチャートが書ける」と「動くプログラムが書ける」のギャップ
フローチャートで理解した気になっていたことが、実際にプログラムに落とすと別の景色になる。この「わかる」と「できる」のギャップが、この課題で最も強く感じたことだ。
まず、値の入れ替え(スワップ)処理。直感的には「AとBを入れ替える」で済みそうだが、プログラムではそうはいかない。AにBの値を入れた瞬間、Aの元の値が消えてしまうからだ。一時退避変数を用意して、「退避→上書き→復元」の3ステップを正しい順番で行う必要がある。フローチャート上では些細なことに見えるが、この順番を1つ間違えただけで全体が壊れる。
次に、インデックスの管理。「今何番目の要素を見ているか」をずらしながらループを回す──バブルソートでは内側と外側の2つのインデックスを同時に管理するので、複雑さが一段上がる。外側ループが1周進むごとに内側ループの範囲が狭くなる。ここを固定値にしてしまうと、「なぜか最後の方の数字がソートされない」というバグに悩まされる。
さらに厄介なのが「1始まり」か「0始まり」かの問題だ。プログラミング環境によってリストの開始番号が異なる。フローチャートと実装で開始番号が食い違うと、存在しない番号を参照してしまういわゆるoff-by-oneエラーが発生する。これは初学者が最もハマりやすい罠だという。
フローチャートを見ればロジックは理解できる。でも、それをプログラムに変換する段階で、「この条件分岐はどのブロックの中に入れるべきか」「変数の初期化はどこで行うか」といった判断が次々に必要になる。「フローチャートが書ける」と「動くプログラムが書ける」の間にはまだギャップがあることを、この課題で改めて実感した。そしてそのギャップを埋めるのは、結局手を動かして試行錯誤するしかない。
「正しいアルゴリズム」と「良いアルゴリズム」は別物
基本版と改良版を並べてみると、やっていることの本質は同じだ。どちらも正しくソートできる。結果は同じ。でも「良さ」は、無駄を省く工夫の有無で決まる。
この「正しい」と「良い」の違いは、プログラミングに限った話ではない。業務プロセスの設計でも同じことが言える。たとえば承認フロー。全件を上長→部長→役員の3段階で承認するプロセスは「正しい」。でも、金額の大小で承認ルートを変える仕組みを入れれば、大半の案件はもっと速く処理できる。やっていることの本質(承認する)は同じだが、「どこで工夫を入れるか」で効率がまったく変わる。
バブルソートのフラグ1つが承認フローの分岐条件1つに相当する。規模は違えど、考え方は同じだ。アルゴリズムの「良さ」とは、同じ問題をいかに少ない手順で解くかという設計の工夫のこと。教科書で計算量のオーダーを読むだけでは得られない、手を動かしたからこそ身についた感覚だと思う。
「中身を知らなくても使える」から「中身を知っているから判断できる」へ
IT畑でインフラを長くやってきた私にとっても、普段「中身を気にせず使っている」ソート処理がどういう仕組みで動いているかを理解したのは、思った以上に新鮮だった。
データベースのORDER BY句を書くとき、裏側でどんなソートアルゴリズムが動いているかを意識することはほぼない。でも、パフォーマンス問題が起きたとき、「なぜこのクエリが遅いのか」を考える際に、ソートの計算量に対する直感があるかないかで、原因の切り分け速度が変わる。
システムの裏側で何が起きているかを知っている人と知らない人では、障害対応やパフォーマンスチューニングの勘所が変わってくる。「使えればいい」から「中身を理解しているから判断できる」への転換。バブルソートという最もシンプルなアルゴリズムが、その転換のきっかけになったのは意外だった。
この経験は、技術者としてのコミュニケーションにも影響を与えた。たとえば「このバッチ処理が遅い」という報告に対して、「データ量が増えたから遅くなった」と言うのと、「データ量の二乗に比例して処理時間が増えるアルゴリズムを使っているので、データ量が2倍になると処理時間は4倍になる」と説明するのでは、聞き手の理解度がまるで違う。アルゴリズムの基礎を「体感として」持っているかどうかで、技術的な問題を非技術者に説明する精度が変わる。
「手を動かす」ことでしか得られない理解がある
この課題を通じて最も強く感じたのは、「読んで理解する」と「手を動かして理解する」は、到達する理解の深さがまったく違うということだ。
バブルソートの仕組みは、教科書を読めば5分で理解できる。隣同士を比較して入れ替える。それだけの話だ。でも、自分でフローチャートを描き、プログラムに実装し、バグに悩まされ、デバッグで原因を突き止める──この一連のプロセスを経ると、「なぜ二重ループが必要なのか」「なぜ変数の初期化位置が重要なのか」「なぜフラグ1つで効率が変わるのか」が、理屈ではなく体感として身につく。
これは技術に限った話ではない。マネジメントでも、フレームワークを本で読んだだけの人と、実際にプロジェクトで適用して苦労した人では、同じフレームワークに対する理解の厚みがまるで違う。「わかる」と「できる」のギャップは、手を動かすことでしか埋まらない。ビジネススクールの授業でScratchという一見シンプルなツールを使う意味は、まさにこのギャップを体験させることにあったのだと思う。
この課題が次の学びの土台になる
振り返ると、バブルソートの経験は単にソートを学んだというだけでなく、「アルゴリズム的に考える」という思考法の土台を作ってくれた。
問題を分解し、手順に落とし、効率を改善する。入力と出力を定義し、その間のプロセスを設計する。例外を想定し、終了条件を明確にする──これらはすべて、プログラミングに限らずビジネスの問題解決にも通じるスキルだ。
第2回でリストとループという「部品」を手に入れ、第3回でそれを使って「アルゴリズム」を組み立てた。この積み上げの感覚が、次回以降の「ビジネス課題にアルゴリズムを適用する」フェーズへの助走になっている。純粋なプログラミング課題からビジネス課題へ──この橋渡しがテクノベート・シンキングのカリキュラム設計の妙だと、後から振り返って感じる。
次回:ECサイトのリコメンド設計──アルゴリズムをビジネスに適用する
第3回の後半では、プログラミングからビジネス課題に一気に視点が移る。リコメンデーションの設計を通じて、バブルソートで学んだアルゴリズムの考え方を、ビジネスの文脈でどう使うか──次回はその話を書く。