アルゴリズムの考え方がわからない人へ|擬似言語で手順に分解する練習
アルゴリズムの考え方が、そもそも分からない。
解説を読めば納得するのに、自分では思いつかない。そんな状態になっていませんか?
科目Bの勉強をしていると、多くの人がここで止まります。文法は覚えたのに、コードの意図がつかめないという感覚です。
でも大丈夫です。アルゴリズムは、ひらめきで出てくるものではありません。手順に分解する作業を何回かやれば、誰でも同じ道をたどれます。
私はエンジニアとして10年以上、Webシステムの開発や運用に携わってきました。仕事で新しい処理を書くときも、いきなりコードを打つことはまずありません。
やることを日本語で箇条に割ってから、はじめて手が動きます。この順番は、試験の擬似言語でもそのまま通用します。
この記事では、考え方が分からない状態から抜けるための分解のしかたを、実例つきでお伝えします。科目B全体の位置づけを先に確かめたい人は、親記事から読むと流れがつかみやすくなります。
【関連記事】基本情報技術者試験の科目Bとは?擬似言語・アルゴリズム対策を初心者向けに解説
アルゴリズムの考え方がわからなくなる3つの原因¶
はじめに、つまずきの正体を切り分けておきましょう。原因が違えば、やるべきことも変わります。
相談を受けていて多いのは、次の3つです。自分がどれに当てはまるかを考えながら読んでみてください。
| つまずきの形 | 起きていること | 抜け方 |
|---|---|---|
| ひらめき待ち | 思いつくかどうかの問題だと考えている | 手順に分けて書き出す |
| コードから入る | 擬似言語の1行目から読み始めてしまう | 目的と材料を先に決める |
| 完成形を目指す | 最初から正しい答えを書こうとする | 粗い日本語から始める |
3つとも、能力ではなく順番の問題です。順番を入れ替えるだけで、見える景色が変わります。
ひらめきだと思っている間は前に進まない¶
アルゴリズムを、才能のある人が思いつく発明のようにとらえている人は多いです。私も学生のころはそう思っていました。
実際は逆で、決まった型の組み合わせがほとんどです。合計を出す、最大値を探す、並べ替える。科目Bで出るのはこうした定番ばかりです。
型を知っていれば、あとは当てはめるだけになります。まず一覧を眺めて、どんな型があるのかを把握しておくのが早道です。
【関連記事】擬似言語で押さえるアルゴリズム一覧|科目Bで出る型を整理して解説
コードから読み始めると意図が見えない¶
問題用紙を開いて、いきなり1行目から読んでいませんか。これは考え方が見えなくなる典型的な入り方です。
コードは手順の結果であって、手順そのものではありません。結果だけ眺めても、なぜその順番なのかは出てきません。
先に見るべきなのは、関数の名前と引数と戻り値です。何を受け取って何を返すのかが分かれば、途中の処理はその橋渡しだと分かります。
完成形を書こうとすると手が止まる¶
3つ目は、最初から正解を書こうとしてしまう癖です。真面目な人ほどこの罠にはまります。
最初の一歩は、雑な日本語で構いません。むしろ雑なほうが、あとで直しやすくなります。
実務でも、最初に書く設計メモは箇条書きの断片です。きれいに整えるのは、動くと分かってからで十分です。
アルゴリズムは3つの動きしか使わない¶
考え方の土台になる話をします。どんなに複雑に見えるコードも、たった3つの動きでできています。
この3つを知っておくと、初見のコードでも部品に分けて見られるようになります。
| 動きの名前 | 意味 | 擬似言語での書き方 |
|---|---|---|
| 順次 | 上から順に実行する | 代入や計算を並べて書く |
| 選択 | 条件で分かれる | if 〜 endif |
| 繰返し | 同じ処理を何度も行う | for 〜 endfor、while 〜 endwhile |
順次、選択、繰返し。この3つだけです。
科目Bのコードを読むときは、まずこの3つのどれが使われているかを見分けます。そうすると、細かい書き方が分からなくても骨組みはつかめます。
難しく見えるコードは、3つが入れ子になっているだけ¶
では、なぜ科目Bのコードは複雑に見えるのでしょうか。理由は単純で、3つの動きが入れ子になっているからです。
繰返しの中に選択が入り、その中でさらに代入が起きる。行数が増えても、使われている部品は増えていません。
次のコードを見てください。配列の中から60点以上の人数を数えるだけの処理です。
for (i を 1 から tensuu の要素数 まで 1 ずつ増やす)
if (tensuu[i] ≧ 60)
count ← count + 1
endif
endfor
外側が繰返し、内側が選択、その中が順次です。入れ子の深さを意識して読むと、2行目と3行目が何回実行されるのかが見えてきます。
初見のコードに出会ったら、まず字下げの位置を目で追ってください。字下げは、そのまま入れ子の構造を表しています。
日本語の手順に分けてから形を当てはめる¶
考え方を身につける練習は、日本語で手順を書くところから始めます。ここを飛ばすからコードが書けないのです。
たとえば、テストの点数から平均点を出す処理を考えてみます。頭の中でやっていることを、そのまま言葉にしてみてください。
全部の点数を足す。人数で割る。その答えを返す。これで手順は完成です。
書き出した手順を、先ほどの3つの動きに当てはめていきます。足す部分は繰返し、割る部分と返す部分は順次です。
材料と結果を先に決めると迷わない¶
手順を書く前に、もう一つやっておくと楽になることがあります。何を受け取って何を返すのかを先に決めることです。
平均点の例なら、受け取るのは点数の配列、返すのは平均値です。この2つが決まっていれば、途中で迷っても戻ってこられます。
実務では、この2つを決めないまま書き始めると、あとで作り直しになります。試験でも同じで、戻り値を見ないまま読むと選択肢で迷います。
実際に手順を分解してコードにしてみる¶
ここからは手を動かす番です。平均点の例を、最後まで通してやってみましょう。
まず、決めたことを表にしておきます。この整理が設計にあたります。
| 決めること | 今回の中身 |
|---|---|
| 受け取るもの | 点数が入った配列 tensuu |
| 返すもの | 平均点(実数) |
| 使う動き | 繰返しで合計、順次で割り算 |
| 気をつける点 | 配列が空のときに割れない |
表の一番下が、初心者の見落としやすい場所です。要素数が0だと割り算ができないので、条件で分けておく必要があります。
ここまで決まれば、あとは擬似言語に置き換えるだけです。次のように書けます。
○実数型: 平均点(整数型の配列: tensuu)
整数型: i
整数型: goukei ← 0
整数型: kensuu ← tensuu の要素数
if (kensuu = 0)
return 0
endif
for (i を 1 から kensuu まで 1 ずつ増やす)
goukei ← goukei + tensuu[i]
endfor
return goukei ÷ kensuu
日本語で書いた3つの手順が、そのままコードの形になっているのが分かるでしょうか。足す部分が for、割って返す部分が最後の行です。
書けたら必ず値を追います。tensuu が {80, 60, 70} のときを見てみましょう。
| i | tensuu[i] | goukei の値 |
|---|---|---|
| ループ前 | ― | 0 |
| 1 | 80 | 80 |
| 2 | 60 | 140 |
| 3 | 70 | 210 |
ループを抜けた時点で goukei は210、kensuu は3なので、返る値は70です。自分の手で追って同じ数字になれば、手順とコードが一致しています。
この追い方に自信がない人は、表の書き方から固めておくと後が楽になります。
【関連記事】擬似言語のトレース表の書き方|科目Bで変数の値を追う手順を解説
書いたコードは動かして確かめる¶
紙の上だけで終わらせると、間違いに気づけません。ここで使えるのが Giji Academy の擬似言語シミュレーターです。
自分で書いたコードを1行ずつ実行して、変数の値が変わる様子を画面で確認できます。手元の表と画面の値を並べれば、ずれた行がすぐ分かります。
無料で使えるので、手順を分解したらそのまま動かしてみてください。考え方が合っていたかどうかを、その場で確かめられます。
うまくいかないときは手順の粒を小さくする¶
コードにできないときは、日本語の手順がまだ粗いことがほとんどです。一つの手順に2つ以上の作業が入っていないか見直してみてください。
全部の点数を足すという手順は、よく見ると2つに分けられます。点数を1つ取り出す、それを合計に足す、という2段階です。
粒を小さくすると、繰返しの中に入る処理が自然に見えてきます。分解の細かさが、そのままコードの行数になります。
例外の場面を先に書き出しておく¶
手順を分解するとき、もう一つ習慣にしてほしいことがあります。うまくいかない場面を先に挙げておくことです。
平均点の例でいえば、配列が空のときがそれにあたります。この1行を入れたかどうかで、答えの正しさが変わります。
科目Bでも、要素が1個だけのとき、値がすべて同じとき、条件にちょうど一致するときが狙われます。ここは実務でも不具合の出やすい場所で、私は書く前に必ず確認するようにしています。
例外を3つ挙げてから本体を書くと、選択肢で迷う回数が目に見えて減ります。
考え方を鍛える1週間の練習¶
分解のしかたが分かったら、あとは回数です。短い時間でも続けたほうが定着します。
私が新人に勧めているのは、次のような回し方です。1日20分で足ります。
| 日 | やること | ねらい |
|---|---|---|
| 1日目 | 身近な作業を日本語の手順に分ける | 分解に慣れる |
| 2日目 | その手順を3つの動きに当てはめる | 骨組みを見る目 |
| 3日目 | 擬似言語のコードに書き起こす | 型への当てはめ |
| 4日目 | 自分でトレースして値を追う | 正確さ |
| 5日目 | シミュレーターで答え合わせをする | ずれの発見 |
| 6日目 | 過去問のコードを日本語に戻す | 逆方向の練習 |
| 7日目 | 迷った場所だけ見直す | 定着 |
注目してほしいのは6日目です。コードを日本語の手順に戻す練習は、考え方を育てるのに一番効きます。
書く方向と読む方向の両方を行き来すると、初見のコードでも意図を推測できるようになります。ここまで来れば、考え方が分からないという感覚はかなり薄れているはずです。
題材は身の回りから選ぶ¶
何を題材にするか迷ったら、日常の作業から拾いましょう。買い物のレシートの合計、名簿から同じ名前を探す、当番の順番を決める。どれも配列と繰返しで書けます。
身近な作業なら、正しい答えを自分で知っています。だから答え合わせに困りません。
問題を自分で作る方法は、別の記事で詳しくまとめてあります。演習の数が足りないと感じている人は、あわせて読んでみてください。
【関連記事】擬似言語の練習問題が足りない人へ|自分で作って力を付ける方法
知らないアルゴリズムが出ても慌てない¶
本番では、名前も知らない処理が出ることがあります。そこで固まってしまう人は少なくありません。
ですが、分解の練習を積んでいれば対処できます。知らない処理でも、3つの動きに分けて読めば中身は追えるからです。
初見の問題への向き合い方は、こちらの記事で具体的に扱っています。
【関連記事】科目Bの初見問題が解けない人へ|知らないアルゴリズムが出たときの読み方
分からない箇所を言葉にしておく¶
練習中に手が止まったら、その場所を一言メモに残しておきましょう。初期値の置き方で迷った、ループの終わり方が決められなかった、といった粒度で十分です。
同じ場所で何度も止まっているなら、それが自分の弱点です。私も仕事で詰まったときは、原因を短く書き残すようにしています。
理由まで残しておくと、次に同じ形に出会ったときの判断が速くなります。ノートが増えるほど、迷う箇所は減っていきます。
まとめ¶
アルゴリズムの考え方が分からないのは、センスの問題ではありません。手順に分解する工程を飛ばしているだけです。
今日お伝えした流れを、もう一度振り返っておきます。
| 段階 | やること |
|---|---|
| 1 | 受け取るものと返すものを決める |
| 2 | やることを日本語の手順に書き出す |
| 3 | 順次・選択・繰返しに当てはめる |
| 4 | 擬似言語のコードに置き換える |
| 5 | トレースとシミュレーターで確かめる |
この5段階は、実務でコードを書くときの流れとほとんど同じです。試験のためだけの技術ではないので、覚えておいて損はありません。
最初のうちは、分解に時間がかかって当然です。3問も通せば、手順が自然に浮かぶようになります。
自分が書いた手順どおりに値が動いたときの感覚は、読むだけの勉強では得られません。まずは今日、身の回りの作業を一つ、日本語の手順に分けてみてください。