科目Bの繰返し問題が解けない人へ|ループ回数を追うコツ
ループが何回まわったのか、途中で分からなくなる。
繰返しの問題で、答えが1だけずれた経験はありませんか?
考え方は合っていた。処理の意味も分かっていた。それなのに選んだ答えが、正解の一つ隣だった。
この1のずれは、実力不足ではありません。回数を頭の中で数えたときにだけ起きる、決まった形の事故です。
私はエンジニアとして10年以上、Webシステムの開発や運用に携わってきました。実務でも、繰返しの回数が1だけ多い不具合は定番で、リストの最後に空の行が出るような形で表面化します。
その調査でやることは決まっています。ループの入口と出口に印を付けて、まわった回数を書き出すだけです。
科目Bの繰返し問題も、まったく同じ手順で解けます。この記事では例題を1本だけ使って、回数を追い切るところまで実演します。
科目Bの繰返し問題は何を聞いているのか¶
まず、どんな聞かれ方をするのかを押さえておきましょう。ここが決まると、追う値が最初から絞れます。
繰返しがからむ設問は、答えの単位で見ると数種類しかありません。
| 問われ方 | よく出る処理 | 答えの単位 |
|---|---|---|
| 何回繰り返すかを答える | 条件を満たすまで足す、割る | 回数 |
| 何番目で終わるかを答える | 探索、条件に合う最初の要素 | 位置 |
| 最後にいくつになるかを答える | 合計、最大値、積み上げ | 値 |
| 途中で何が起きるかを答える | 空欄補充、条件の入れ替え | 処理の中身 |
厄介なのは、この4つが同じコードから出題できてしまうことです。回数を数える変数と、値をためる変数が、1つのループの中に同居しているからです。
だから設問文を読まずにコードから入ると、両方を追うはめになります。追う値が2つあると、表が長くなって時間が足りません。
科目B全体の中で繰返しの問題がどこに位置するのかを先に見ておきたい人は、こちらから読むと土台が固まります。
【関連記事】基本情報技術者試験の科目Bとは?擬似言語・アルゴリズム対策を初心者向けに解説
whileとforのどちらが出ているかで読み方が変わる¶
同じ繰返しでも、forとwhileでは危ない場所が違います。ここを混ぜて読むと、確認する場所を間違えます。
forは回数がほぼ書いてあります。1から要素数まで、と宣言されているので、まわる回数は行を見れば分かります。
一方でwhileは、回数がどこにも書いてありません。条件が偽になるまで、としか決まっていないので、実際に値を動かさないと回数が出ないのです。
繰返しの文法そのものに不安が残っているなら、先に整理しておくほうが早いです。
【関連記事】擬似言語のwhileとforってどう違う?繰返し処理で迷子にならない方法を詳しく解説
段1:回数を聞かれているのか、値を聞かれているのか¶
最初にやるのはコードを読むことではなく、答えの単位を1つに決めることです。
回数を聞かれているのに合計を追っていたら、途中の計算がすべて合っていても外れます。逆に単位さえ決まれば、表に書く列も自動的に決まります。
設問文を先に読んで、余白に一言だけ書く¶
問題は、説明文、擬似言語のコード、設問文という並びで載っていることが多いです。上から順に読む必要はありません。
設問文まで飛ばして読み、答えの単位を決めてからコードに戻ってください。回数、値、位置。この程度の短い言葉を余白に書いておくだけで十分です。
追っている途中で目的を見失っても、そのメモを見れば戻ってこられます。数秒の手間で読み直しを一度防げるなら、割に合います。
回数を数える変数を1つだけ決める¶
繰返しの中には、更新される変数がいくつも並びます。全部を同じ重さで追うと、表が横に伸びて手が止まります。
答えが回数なら、回数を数えている変数を1つだけ主役に決めてください。残りの変数は、その主役が変わる理由を説明するための脇役です。
主役の見分け方は簡単で、1ずつ増える代入だけを持っている変数がそれにあたります。合計や最大値のように、値の中身で増え方が変わる変数は主役ではありません。
段2:繰返しのコードはこの3か所から見る¶
答えの単位が決まったら、コードに移ります。ここでも上から順には読みません。
ここからは例題を使います。試験でよく見る形に寄せて、私が書いたものです。
○整数型: 到達回数(整数型の配列: 売上, 整数型: 目標)
整数型: i, 合計, 回数
合計 ← 0
回数 ← 0
i ← 1
while (合計 < 目標 and i ≦ 売上の要素数)
合計 ← 合計 + 売上[i]
回数 ← 回数 + 1
i ← i + 1
endwhile
if (合計 < 目標)
return -1
endif
return 回数
日ごとの売上を先頭から足していき、目標に達するまでに何日かかったかを返す処理です。設問は、売上が30、20、50、40、60で目標が120のとき、返される値はいくつか、としましょう。
このコードで先に見る場所は3か所だけです。順番も決まっています。
| 順番 | 見る場所 | そこで分かること |
|---|---|---|
| 1 | ループに入る前の代入 | 回数と合計がどこから始まるか |
| 2 | whileの条件 | どうなったら止まるか |
| 3 | ループの中の更新 | 1周で何がいくつ変わるか |
この3つは、初期値、条件、更新と呼ばれます。回数のずれは、必ずこのどれかの見落としから生まれます。
初期値が0なのか1なのかを最初に確かめる¶
回数が0から始まるコードと、1から始まるコードがあります。見た目はほとんど変わりませんが、答えはきれいに1ずれます。
今回は回数が0から始まり、ループの中で1ずつ増えます。つまり回数は、実際にまわった数と一致します。
もし回数が1から始まっていたら、まわった数より1多い値が返ります。宣言のすぐ下にある代入は、飛ばさず必ず読んでください。
止まる条件は、ループを抜けた瞬間の姿で読む¶
2か所目はwhileの条件です。今回は合計が目標未満で、かつiが要素数以内、という2つがandで結ばれています。
andで結ばれた条件は、どちらか一方が偽になった時点で止まります。つまり止まり方が2通りあるということです。
目標に達して止まったのか、要素を使い切って止まったのか。この違いがそのまま、最後のifの分岐につながっています。
複合条件の読み違いが不安な人は、条件の側を先に固めておくと繰返しの問題が一気に軽くなります。
【関連記事】擬似言語の論理演算(and・or・not)の読み方|複合条件で迷わないコツを解説
段3:回数を表にして追う¶
見る場所が決まったので、値を入れていきます。この段のルールは1つで、頭の中で数えないことです。
書く列は段2の時点で決まっています。今回はi、売上[i]、合計、回数の4列です。
売上が30、20、50、40、60で目標が120のとき、1周ごとの状態は次のようになります。
| 周 | 売上[i] | 合計 | 回数 | 次の条件判定 |
|---|---|---|---|---|
| 1 | 30 | 30 | 1 | 30 < 120 なので続く |
| 2 | 20 | 50 | 2 | 50 < 120 なので続く |
| 3 | 50 | 100 | 3 | 100 < 120 なので続く |
| 4 | 40 | 140 | 4 | 140 < 120 が偽で止まる |
答えは4です。5日目の60は足されないまま、ループが終わります。
この表で効いているのは一番右の列です。1周終わるたびに条件を判定し直す、という動きが目に見える形で残ります。
繰返しの問題で答えがずれる人は、この判定の列を書いていないことがほとんどです。書けば、止まる瞬間を見落としようがありません。
ループを抜けた後の値も1行だけ書き足す¶
表を4行で止めてしまうと、iの最終値が分かりません。ループの中でiは5になっていますが、5周目は実行されていないからです。
抜けた直後の状態を、表の下に1行だけ書き足してください。合計は140、回数は4、iは5。この3つが揃っていれば、後ろのifも安心して読めます。
今回は合計が目標以上なので、-1を返す分岐には入りません。返るのは回数の4です。
トレース表の書き方そのものを固めたい人は、手順を分解したこちらから練習するのが近道です。
【関連記事】擬似言語のトレース表の書き方|科目Bで変数の値を追う手順を解説
回数が多いときは3周だけ書いて規則を見る¶
要素が20個あるループを20行書いていたら、時間が足りません。本番では途中で切り上げる判断も必要です。
3周ほど書いて増え方の規則が見えたら、そこから先は計算で飛ばして構いません。ただし止まる直前と直後の2周だけは、必ず手で書いてください。
答えがずれるのは、たいていその2周です。真ん中を省略しても、端を省略しなければ表は効きます。
段4:1回ずれた選択肢を見分ける¶
答えが出たら、そのまま選ばずに一度止まります。繰返しの問題は、1だけ違う選択肢が必ず並んでいるからです。
出題する側は、途中でつまずいた人がたどり着く値を選択肢にしています。今回のコードで作れる誤答を表にまとめました。
| 誤答 | どこで生まれるか | 見分け方 |
|---|---|---|
| 3 | 目標を超える前の周までを数えた | 合計を更新してから回数を増やす順番を確かめる |
| 5 | 回数ではなくiの最終値を答えた | returnが返している変数を読み直す |
| 140 | 回数ではなく合計を答えた | 設問が聞いている単位に戻る |
| -1 | 止まった理由を取り違えた | 抜けた時点の合計と目標を比べ直す |
この4つで、繰返し問題の誤答のかなりの部分が説明できます。答えを出したあと、右の列を上から当てはめるだけでも精度が上がります。
とくに1行目は頻出です。合計が目標に届いた周を数えるのか、届く前の周までを数えるのかは、コードの行の順番だけで決まります。
空欄補充の型なら、止まる直前の周に入れて試す¶
繰返しの問題は、条件や更新の一部が空欄になっている型でもよく出ます。この型では、答えを自分で組み立てなくて構いません。
残った選択肢を空欄に入れて、止まる直前の1周だけ動かしてみてください。全部の選択肢を全周まわす必要はありません。
境目の周を選ぶのがコツです。今回のコードなら、合計が100から140に変わる4周目に入れて試すと差がはっきり出ます。
その1回で、条件が以上なのか超過なのかによる違いも同時に確かめられます。時間が押しているときほど、この試し方が頼りになります。
多重ループの問題では、内側と外側のどちらの回数を聞かれているかでも答えが変わります。二重の形に慣れておきたい人はこちらもどうぞ。
【関連記事】擬似言語の多重ループ(入れ子の繰返し)がわからない人へ|二重forの読み方を解説
段5:シミュレーターで動かして答え合わせをする¶
最後の段は、本番ではなく勉強中にやることです。ここを入れるかどうかで、伸び方がはっきり変わります。
自分の書いた表と、実際に動かした結果を突き合わせてください。合っていれば、その読み方はもう固まっています。
Giji Academy の擬似言語シミュレーターなら、一行ずつ進めながら回数と合計が変わる瞬間を画面で追えます。紙の表と画面の値がずれた行が、そのままあなたの弱点です。
ずれる場所には癖があります。抜けた直後の1行だったり、条件が以上か超過かの判定だったり、人によってほぼ決まっています。
その1か所を潰すだけで、同じ型の問題がまとめて解けるようになります。問題数を増やすより、ずっと効率がいいはずです。
動かすときは、目標の値を変えてみるのが効きます。目標を1000にすれば、要素を使い切って-1が返る道を目で確かめられます。
私が現場で新人のコードをレビューするときも、見るのはまず境目です。最初の1周と最後の1周が正しければ、途中はたいてい正しく動きます。
配列を先頭から追う型の問題も、考え方は今日と同じです。添字の側から整理したい人は、こちらと合わせて読むと定着が早くなります。
【関連記事】科目Bの配列問題の解き方|添字を表にして追う方法
まとめ¶
最後に、繰返し問題を解く順番を振り返っておきます。
始まりは設問文です。答えが回数なのか値なのか位置なのかを決めてから、コードに移ります。
コードで先に見るのは、初期値、止まる条件、1周ごとの更新の3か所です。この時点で追う変数は1つに絞れています。
そのうえで表を書きます。条件判定の列を右端に置き、抜けた直後の1行まで書き足すのが、1のずれを防ぐいちばん確実な方法です。
答えが出たら、回数と合計の取り違えや、止まった理由の読み違いを当てはめて確かめます。そして勉強中は、動かして答え合わせをするところまでを1セットにしましょう。
回数は数えるものではなく、書いて確かめるものです。今日はまず1問だけ、条件判定の列を足したトレース表を書いてみてください。