科目Bの初見問題が解けない人へ|知らないアルゴリズムが出たときの読み方
見たことのないアルゴリズムが出た瞬間、頭が真っ白になった。
過去問なら解けるのに、本番の初見問題で手が止まってしまうことはありませんか?
科目Bの勉強を進めていくと、必ずこの壁にぶつかります。解いたことのある問題は正解できるのに、少し形の違う問題になると急に読めなくなる。
その状態のまま本番を迎えるのが、一番こわいパターンです。試験で出るのは、まだ誰も解いたことのない新しい問題だからです。
私はエンジニアとして10年以上、Webシステムの開発や運用に携わってきました。実務でも、他人が書いた見たことのないコードを読む場面のほうが、自分でゼロから書く場面よりずっと多いのが実情です。
そして最初は誰でも読めません。読み方の手順を持っているかどうかだけが、差になります。
この記事では、知らないアルゴリズムが出たときにどこから読み始めればいいのかを、例題を追いながら整理していきます。
科目Bの初見問題とは何か¶
まずは、自分が何と戦っているのかをはっきりさせておきましょう。相手の正体が分かると、対策の方向も決まります。
科目Bは、20問を100分で解く試験です。そのうち16問がアルゴリズムとプログラミングから出題されます。
この16問は、毎回新しく作られた問題です。つまり受験者にとっては、原則としてすべてが初見問題ということになります。
過去問と同じ問題は出ないという前提¶
ここを勘違いしたまま勉強を続けている人が、意外なほど多くいます。公開されている問題を覚えれば本番でも通用する、という感覚です。
科目Bで公開されている問題は、そう多くありません。それを何度も解けば答えは覚えられますが、覚えた答えは本番で一度も使えません。
では公開問題を解く意味がないのかというと、そうではありません。使い方が違うだけです。
公開問題は、答えを覚えるためではなく、読み方を身に付けるための素材として使います。この使い分けについては、こちらの記事で詳しく整理しています。
【関連記事】科目Bの擬似言語問題の解き方|コードを読む順番を例題で解説
初見でも解けるように作られている¶
不安になる話が続いたので、ここで安心できる話をします。科目Bの問題は、知識がなくても解けるように設計されています。
問題文には、そのアルゴリズムが何をするものなのかという説明が必ず添えられています。名前を知らなくても、説明とコードだけで答えにたどり着ける形になっています。
裏を返すと、有名なアルゴリズムを片っ端から暗記する勉強は、費用対効果がよくありません。覚えた名前が出題される保証はどこにもないからです。
必要なのは知識の量ではなく、その場でコードを読み解く手順です。ここから先は、その手順の話をしていきます。
初見問題で手が止まる三つの原因¶
手順の話に入る前に、なぜ止まってしまうのかを見ておきましょう。原因が分かると、直すべき癖もはっきりします。
私がこれまで見てきた限り、初見問題で固まる人の詰まり方は、だいたい次の三つに分かれます。表にまとめました。
| 詰まり方 | 頭の中で起きていること | 直し方 |
|---|---|---|
| 名前を知らないと解けないと思う | 知識の問題だと考えて記憶を探しに行く | コードは説明文の言い換えだと考える |
| 全部読んでから考えようとする | 最後まで読んでも全体像がつかめず戻る | 戻り値と宣言だけ先に見る |
| 頭の中だけで考える | 変数の値が追えず途中で混ざる | 小さい値を実際に入れて紙に書く |
三つとも、能力ではなく手順の問題です。だから直せます。
名前を知らないと解けないと思っている¶
一番多いのがこの詰まり方です。見慣れない処理が出た瞬間、これは習っていない、と感じて思考が止まります。
でも思い出してみてください。科目Bのコードは、問題文に書かれた説明を擬似言語に置き換えたものにすぎません。
説明文が日本語で、コードが擬似言語というだけの違いです。両者は同じことを言っています。
だから読めないと感じたときは、問題文の説明にもう一度戻ります。そこにコードの意味が書いてあります。
全部読んでから考えようとしている¶
二つ目は、読む順番の問題です。1行目から最後まで順番に読み、それから考えようとする読み方です。
この読み方だと、途中で何を追っていたか分からなくなります。長いコードほど、最後まで読んだ時点で最初の内容が抜けてしまうからです。
コードは上から順に読むものではありません。先に結論を見てから、その結論を作っている部分に降りていくほうが速く理解できます。
具体的な値を入れずに考えている¶
三つ目は、頭の中だけで処理を追おうとするパターンです。変数が二つまでなら何とかなりますが、三つを超えると急に破綻します。
これは記憶力の問題ではありません。人間の頭は、複数の値の変化を同時に保持できるようにできていないだけです。
だから紙に書きます。書いた瞬間に、追えなかった処理が追えるようになります。
知らないアルゴリズムを読む四つの手順¶
原因が整理できたところで、実際の手順に入りましょう。初見のコードに出会ったとき、この順番で見ていきます。
私が実務でも使っている読み方を、試験向けに整理したものです。全体像を先に表で示します。
| 順番 | 見る場所 | そこで確かめること |
|---|---|---|
| 1 | 問題文の説明と手続の名前 | この処理は結局、何を返すのか |
| 2 | 引数と変数の宣言 | 何を受け取り、何を覚えておくのか |
| 3 | ループの中身 | 1周ごとに何が変わるのか |
| 4 | 小さい入力でトレース | 実際の値の動きが説明と合うか |
この順番には理由があります。1と2で全体の枠を決めてから、3と4で中身を埋めていく形になっているからです。
手順1と2:戻り値と宣言から読む¶
最初に見るのは、コードの中ほどではなく両端です。何を受け取って何を返すのかが分かれば、途中の処理の役割も見当がつきます。
戻り値が整数型なら、数を数えているか、位置を返しているか、合計を出しているかのどれかです。配列を返すなら、並べ替えや絞り込みの可能性が高くなります。
次に変数の宣言を見ます。ここには、その処理が何を覚えておく必要があるのかが表れます。
たとえば整数型の変数が二つあり、片方が0で初期化されていれば、それは数を数えるための入れ物である可能性が高いでしょう。集計処理の典型的な形については、こちらの記事にパターンをまとめてあります。
【関連記事】擬似言語の合計・最大値・件数の求め方|科目Bで頻出の集計パターンを解説
手順3と4:小さい入力でトレースする¶
枠がつかめたら、いよいよ値を動かします。ここで大事なのは、入力を思い切り小さくすることです。
要素が10個ある配列で試す必要はありません。4個か5個で十分に処理の性格は見えてきます。
トレース表の書き方そのものに不安がある人は、先にこちらで手順を確認しておくと、この先が読みやすくなります。
【関連記事】擬似言語のトレース表の書き方|科目Bで変数の値を追う手順を解説
例題:初見のコードを読んでみる¶
ここまでの手順を、実際のコードで試してみましょう。あえて名前を伏せた処理を用意しました。
次のコードは、この記事のために自作した類題です。何をする処理なのか、読みながら考えてみてください。
○整数型: 処理X(整数型の配列: data)
整数型: i
整数型: 基準, 個数
基準 ← data[1]
個数 ← 1
for (i を 2 から dataの要素数 まで 1 ずつ増やす)
if (data[i] > 基準)
基準 ← data[i]
個数 ← 個数 + 1
endif
endfor
return 個数
さて、手順どおりに見ていきます。まず戻り値は整数型で、返しているのは個数という名前の変数です。
宣言を見ると、基準と個数という二つの整数型があります。個数は1で初期化されているので、何かを数えていると考えられます。
ループの中では、data[i] が基準より大きいときだけ、基準を更新して個数を増やしています。つまり数えているのは、それまでの最大値を超えた回数です。
トレース表で確かめる¶
読み取った内容が正しいかどうかは、値を入れてみれば分かります。data が {3, 1, 4, 1, 5} の場合で追ってみましょう。
ループに入る前の状態は、基準が3で個数が1です。ここから1周ずつ見ていきます。
| i | data[i] | 条件の判定 | 基準 | 個数 |
|---|---|---|---|---|
| 開始前 | ー | ー | 3 | 1 |
| 2 | 1 | 1 > 3 は偽 | 3 | 1 |
| 3 | 4 | 4 > 3 は真 | 4 | 2 |
| 4 | 1 | 1 > 4 は偽 | 4 | 2 |
| 5 | 5 | 5 > 4 は真 | 5 | 3 |
戻り値は3になりました。3、4、5の三つが、それぞれ登場した時点での最大値だったということです。
この処理には教科書に載るような名前はありません。それでも、何をしているかは説明できました。
名前は後から付ければいい¶
いま起きたことを振り返ってみてください。名前を知らないまま、処理の内容を正しく言い当てられています。
これが初見問題を解くということです。知識を取り出すのではなく、目の前のコードから意味を組み立てる作業になります。
自分の言葉で「これまでの最大値を更新した回数を数える処理」と言えれば、設問には十分に答えられます。名前は、解いた後で付けても遅くありません。
間違いやすい選択肢の見分け方¶
読み方が分かったところで、答えを選ぶ段階の話もしておきます。ここにも決まった落とし穴があります。
科目Bの選択肢は、正解と惜しいものが必ず混ざる形で作られています。惜しいものの外し方を知っておくと、正答率が安定します。
端の1回で差がつく¶
さきほどの例題で、個数の初期値が1だったことを思い出してください。0ではなく1から始まっていました。
もし初期値が0のまま同じループを回すと、答えは2になります。最初の要素を数え忘れるからです。
選択肢に3と2が両方あったら、出題者はまさにここを狙っています。ループの外側にある1回分を、意図的に見落とさせる作りです。
こういう1回のずれは、頭の中では絶対に気づけません。トレース表の最初の行、つまりループに入る前の状態を必ず書くのが、唯一の防ぎ方になります。
不等号の向きひとつで答えが変わる¶
もう一つ、例題を使って確かめておきたい落とし穴があります。条件式の不等号です。
さきほどのコードは data[i] > 基準 でした。これを data[i] ≧ 基準 に変えると、どうなるでしょうか。
同じ値が並んでいたときの扱いが変わります。等しい値でも更新されるので、個数はその分だけ増えることになります。
設問が空欄補充の形をとっているとき、選択肢に > と ≧ の両方が並ぶことは珍しくありません。同じ値が入った入力で試すと、どちらが正しいかがはっきりします。
選択肢を先に見ない¶
もう一つ、本番でやりがちな癖があります。コードを読む前に選択肢を眺めてしまうことです。
先に選択肢を見ると、それらしいものに引っ張られます。自分でトレースした結果よりも、見覚えのある形を信じてしまうからです。
読む、追う、それから選ぶ。この順番を崩さないだけで、取りこぼしは減っていきます。
本番で時間が足りなくなったら¶
最後に、現実的な話をしておきます。初見問題は、どうしても時間を食います。
丁寧にトレースすれば解けると分かっていても、20問すべてにその時間は使えません。ここで必要になるのが、飛ばす判断です。
初見のコードを2分ほど眺めて、何をする処理なのか見当もつかない場合は、いったん飛ばします。後半に易しい問題が残っている可能性があるからです。
大事なのは、飛ばすことを負けだと思わないことです。試験は全問正解を競うものではありません。
1問あたりにかけられる時間の目安や、見直しの順番については、こちらの記事で具体的に整理しています。
【関連記事】基本情報 科目Bの時間配分|1問にかけられる時間と見直しの順番
読む速さは演習量でしか上がらない¶
飛ばす判断を減らすには、結局のところ読む速さを上げるしかありません。そしてこれは、読んだ量に比例して伸びます。
おすすめは、初めて見るコードを毎日1本だけ読む習慣です。答えを出すところまでやらなくても、何をする処理かを一言で説明できれば十分です。
Giji Academy の擬似言語シミュレーターを使うと、コードを1行ずつ動かしながら変数の値を確認できます。自分のトレースが合っていたかどうかを、その場で答え合わせできる形です。
紙に書いた表と画面の値を見比べると、自分がどこでずれるのかが見えてきます。この繰り返しが、初見への強さに変わっていきます。
科目Bという試験の全体像から確認し直したい人は、親記事にあたるこちらから読んでみてください。
【関連記事】基本情報技術者試験の科目Bとは?擬似言語・アルゴリズム対策を初心者向けに解説
まとめ¶
最後に、この記事の要点を振り返ります。
科目Bのアルゴリズム問題は16問すべてが新作です。初見であることは例外ではなく、前提だと考えてください。
そして問題は、知識がなくても解けるように作られています。名前を覚える勉強より、その場で読む手順を持つほうが本番で効きます。
読む順番は、戻り値と宣言から入り、ループの中身を見て、小さい値でトレースする流れです。頭の中だけで追わず、必ず紙に書きましょう。
選択肢を選ぶときは、ループに入る前の1回分に注意してください。惜しい選択肢は、たいていそこで作られています。
見たことのないコードでも、読み方さえ持っていれば意味は組み立てられます。今日の勉強では、初めて見るコードを1本だけ開いてみましょう。