擬似コード (pseudocode) の基本:言語に縛られずアルゴリズムを書く
擬似コードとは何か
アルゴリズムを Python や C++ など実在する言語で書き始めると、セミコロンやインデント、型宣言といった文法の細部に意識が向きがちです。擬似コード (pseudocode) は、特定の言語の文法から離れて、アルゴリズムの手順そのものを表すために使われる記法です。
擬似コードはコンピュータに直接実行させるためのものではなく、人間が解法を読み書きするための道具です。論文、教科書、技術面接、設計メモなど、使用言語が統一されていない場でアルゴリズムを共有したいときに使われます。
なぜ擬似コードを使うのか
擬似コードを挟む利点は次のあたりです。
- 文法エラーを気にせず、手順そのものに集中できる
- 言語経験が異なるメンバー同士でも共有しやすい
- 実装前にアルゴリズムの正しさを検討しやすい
- コードレビューより前の設計段階で議論できる
実装の前に考えるための共通言語、と捉えるとわかりやすいです。
よくある記法
擬似コードには厳密な統一規格はありませんが、多くの資料で次のような書き方が共通して使われています。
←: 代入 (右辺の値を左辺の変数に入れる)=: 値が等しいかどうかの比較if ... then ... else: 条件分岐for,while: 繰り返しreturn: 結果を返して終了- インデント: 字下げによって処理のまとまり (ブロック) を示す
たとえば
x ← x + 1
は、「今の x の値に 1 を足し、その結果をあらためて x に代入する」という意味です。数学の式として x = x + 1 を書くと両辺が矛盾しますが、擬似コードでは代入という別の意味で使われることがあります。混乱を避けるため、代入には ← を使う流儀が広く見られます。
読み方の基本
擬似コードを読むときは、上から順に 1 行ずつ、変数の値がどう変わっていくかを追うのが基本です。慣れないうちは、各行で変数がどの値を持つかを紙に書き出しながら読むと把握しやすくなります。
次の例を見てください。
Algorithm SumToN(n)
total ← 0
for i ← 1 to n
total ← total + i
return total
これは $1 + 2 + \dots + n$ を計算するアルゴリズムです。n = 4 として追うと、
- 最初に
total = 0 i = 1のときtotal = 0 + 1 = 1i = 2のときtotal = 1 + 2 = 3i = 3のときtotal = 3 + 3 = 6i = 4のときtotal = 6 + 4 = 10
となり、最後に 10 を返します。「いまどの行を実行していて、どの変数がどう変わったか」を意識するのが読み方のコツです。
条件分岐の読み方
if 文は、条件が真 (成り立つ) なら上の枝、偽 (成り立たない) なら下の枝に進むという意味です。
if score ≥ 80
grade ← "A"
else
grade ← "B"
この場合、score が 80 以上なら grade に "A" を、そうでなければ "B" を入れます。一見複雑な擬似コードでも、条件分岐は「どちらの道に進むかを決めているだけ」と捉えると読みやすくなります。
ループの読み方
ループは同じ種類の処理を繰り返すための仕組みです。擬似コードでは次の 2 種類がよく登場します。
for ループ
回数があらかじめ決まっている繰り返しに向きます。
for i ← 0 to n - 1
process A[i]
これは i を 0, 1, ..., n - 1 と順に動かしながら、配列 A の各要素 A[i] に同じ処理を適用するイメージです。たとえば n = 3 なら、A[0], A[1], A[2] の順に process が呼ばれます。
while ループ
条件が成り立つ間だけ繰り返したいときに使います。
while x > 0
x ← x - 1
ここでは x が正の間はループが続き、毎回 x が 1 ずつ減るので、いずれ x = 0 になって停止します。x = 3 から始めれば 3 → 2 → 1 → 0 と動いて 0 で止まります。
擬似コードを書くときの基本ルール
擬似コードを書くときは、次の点を意識すると読みやすくなります。
1. 入力と出力を意識する
何を受け取り、何を返すのかが最初にわかるようにします。関数名や引数名には、役割が読み取れるものを選びます。たとえば単に f(x) と書くよりも、BinarySearch(A, target) のほうが意図が伝わります。
2. 変数名を雑にしない
x, y, z だけで済ませると、後から読み返したときに意味がとりにくくなります。max_value, count, left, right のように役割の見える名前のほうが読みやすくなります。
3. インデントを揃える
条件分岐やループの中身は字下げしてまとまりを示します。インデントが崩れると、どの処理がループや if の内側にあるのかが読み取りにくくなります。
4. 省略しすぎない
書いた本人にはわかっていても、読み手には伝わらないことがあります。終了条件、変数の更新処理、返り値は省略せず明示しておくと誤読が減ります。
例: 最大値探索を書く
配列 A の最大値を求める擬似コードは、次のように書けます。
Algorithm MaxValue(A)
max_value ← A[0]
for i ← 1 to length(A) - 1
if A[i] > max_value
max_value ← A[i]
return max_value
たとえば A = [3, 1, 4, 1, 5] の場合、max_value は 3 → 3 → 4 → 4 → 5 と更新され、最終的に 5 が返ります。この擬似コードのポイントは、
max_valueが何を表すか名前だけで読み取れる- ループの範囲が
1からlength(A) - 1まで明示されている - 更新する条件が
ifで明確に書かれている - 最後に何を返すかがはっきりしている
という点です。短いコードでも、手順としての意味が読み取れる形になっています。
自然言語から擬似コードに落とす方法
頭の中のアイデアを擬似コードにするときは、最初から整った形を目指さなくて構いません。次の順で整理すると書きやすくなります。
- 問題文を見て、入力と出力を 1 文で言い直す
- 解法を日本語の箇条書きにする
- その箇条書きを
if,for,while,returnに置き換える - 変数名を意味のある名前に直す
たとえば「配列の中に x があるか調べる」という問題なら、日本語では次のように書けます。
- 先頭から順に見ていく
- 一致したら「見つかった」と返す
- 最後まで一致しなければ「見つからなかった」と返す
これをそのまま擬似コードに直したのが次です。
Algorithm LinearSearch(A, x)
for i ← 0 to length(A) - 1
if A[i] = x
return true
return false
これは線形探索 (linear search) と呼ばれる方法で、配列の先頭から 1 つずつ x と比較していくシンプルなアルゴリズムです。
まとめ
擬似コードは、アルゴリズムの手順を特定の言語に依存せずに表すための道具です。読むときは変数の状態変化を 1 行ずつ追い、書くときは入力・出力・条件・繰り返し・返り値を明示することがポイントです。