令和8年度の科目B、その3問目です。科目Bには、擬似言語(IPAが試験用に決めた、日本語まじりのプログラムの書き方)で書かれたプログラムを読む問題があり、この問3もその1つです。関数が2つ、選択肢が8つあって、いちばん重たく見える問題です。でも8つを見比べるところから始めるのは、いちばん遠回りです。先にプログラムを読み切ってしまえば、入れるべき式は自分で書けます ── 解答群は、書いた式と同じ形を探すときに見るだけです。
出題
まず原文のまま読んでみてください。記号の読み方は、この下の「この問題に出てくる記号」にまとめてあります。読めなくてもここでは問題ありません。
出典:令和8年度 基本情報技術者試験 科目B 公開問題 問3
次のプログラム中の に入れる正しい答えを,解答群の中から選べ。ここで,配列の要素番号は1 から始まる。
関数func1 に与える引数と,関数func2 に与える引数とが同じとき,二つの関数は同じ値を返す。プログラムでは,配列の領域外を参照してはならないものとする。
〔プログラム〕
○整数型: func1(整数型: n)
if (nが2以下)
return 1
endif
return 2 × func1(n - 2) + func1(n - 1)
○整数型: func2(整数型: n)
整数型の配列: data ← {1, 1, 1}
整数型: i
/* nが3より小さいときは繰返し処理を実行しない */
for (iを3からnまで1ずつ増やす)
data[1] ← data[2]
data[2] ← data[3]
data[3] ←
endfor
return data[3]
解答群
ア 2 × data[1] + data[2]
イ 2 × data[2] + data[1]
ウ 2 × data[i - 1] + data[i - 2]
エ 2 × data[i - 2] + data[i - 1]
オ data[3] + 2 × data[1] + data[2]
カ data[3] + 2 × data[2] + data[1]
キ data[3] + 2 × data[i - 1] + data[i - 2]
ク data[3] + 2 × data[i - 2] + data[i - 1]
答えだけ先に見る
正解は ア です。その式が何で、なぜアになるのかは、解答群を見る前に自分で組み立てて確かめます(先に式まで見てしまうと、組み立てをなぞるだけになります)。
まず、通しで見る
5分ほどの動画です(音声つき)。この空欄を自分で決められるようになります。8つの選択肢は途中まで見ません。先にプログラムのほうを読み切ってしまうと、入れるべき式はひとりでに出てきます。
再帰がはじめてでも追えるように、func1 の値も式ごと1つずつ出しています。最後は n が 5 のときを1周ずつ、ずらして、計算して、書き足すところまで通します。どの周で何が起きたかが、積み上がった表で残ります。
箱の中身を確かめてから、式を決める(5分7秒・音声つき)
再生できないときは、この下の説明とシミュレータで同じ内容を追えます。
ここから、同じ内容を1つずつ確かめていきます。
この問題に出てくる記号
いま読めればいいのは、11コだけです。細かいところは、使う場面で足していきます。
| 書き方 | 読み方 |
|---|---|
○整数型: func1(…) |
○ は関数がここから始まるという印(関数=ひとまとまりの処理につけた名前)。うしろの 整数型 は返す値の型(型=入れてよい値の種類。整数型 なら整数だけ)。この問題では関数が2つ並んでいます |
整数型の配列:data ← {1, 1, 1} |
箱をいくつか用意して、はじめの値を入れる宣言。{1, 1, 1} なので箱は3つで、この問題では増えも減りもしません。整数型: i のように の配列 が無ければ箱は1つ |
a ← b |
右の値を、左へ入れる。左は上書き、右はそのまま。この問題は、この向きで決まります |
data[1] |
配列 data の1番目の箱。角かっこの中の数字は問題文でいう要素番号(この記事では短い添字と書きます)。data[i - 1] と式でも書けますが、その番号の箱が実在するかは自分で確かめます |
for (…)endfor |
あいだの行をくり返す。iを3からnまで1ずつ増やす なら i が 3, 4, 5, … n と動きます。くり返しの1回ぶんを、この記事では「1周」と呼びます |
if (…)endif |
かっこの中が成り立つときだけあいだの行を実行し、成り立たなければ endif の次へ飛びます |
return ◯ |
◯ を返して、その関数はそこで終わり。以降の行は実行されません。返した値は、その関数を呼んだ場所に入ります |
2 × a + b |
掛け算が先。(2 × a) + b という意味です |
/* … */ |
コメント。人が読むための書き込みで、実行されません |
func1(整数型: n) |
括弧の中は受け取る値の型と名前(この値を引数といいます)。func1(5) なら n に 5 が入って始まります |
func1(n - 2) |
自分と同じ名前の関数を呼ぶ書き方=再帰。式に func1(1) と書けば、その場所に「func1 を n = 1 で動かした結果」が入ります。引数が小さくなっていくので、いつか nが2以下 に行き着いて止まります |
もう1つ、記号ではありませんが問題文の「配列の領域外を参照してはならない」=用意した箱の外を読んではいけないという条件が、あとの答え合わせで効いてきます。
これで手が止まるところがあれば、下の教科書から先にそこだけ拾ってきてください(G5 のような番号は、当サイトの擬似言語の教科書の第何回かを表します)。
data[1] ← data[2] のどちらが読まれ、どちらが書かれるかG3-3戻り値 ─ return で何が呼び出し元へ渡るかG8-1演算子と優先順位 ─ × と + はどちらが先かまず、できあがりを見る ── func1 の値
この節で使うのは、問題文のうち1つだけです。「同じ引数を渡したら、2つの関数は同じ値を返す」。つまり func2 は、func1 と同じ値を出す機械でなければいけません。
ということは、先に func1 の値を出しておけば、物差し(=func2 が正しいかを測る基準の値)になります。func1 は自分を呼ぶので難しく見えますが、行き先は2つしかありません。
○整数型: func1(整数型: n)
何番目の値がほしいかを n で受け取る
if (nが2以下)
道A ── n が 1 か 2 なら、この中へ入る
return 1
道A ── 値は 1。計算せずに、ここで終わり
endif
if の範囲はここまで
return 2 × func1(n - 2) + func1(n - 1)
道B ── n が 3 以上のときだけ、この行に来る。2つ前を2倍して、1つ前を足す
※ 右側の注釈は当サイトで書き加えたものです。プログラム自体は原文のまま引用しています。
日本語にすると、この2つだけです(「道A」「道B」は当サイトでの呼び名)。
func1 の決まりは、2つ
道A n が 1 か 2 のとき → 値は 1(計算しない)
道B n が 3 以上のとき → 値は 2 × (2つ前の値) + (1つ前の値)
道Bは自分より小さい n で自分を呼ぶので、いつか道Aに行き着いて止まります。道Aが無いと、いつまでも止まりません。
これを、n の小さいほうから順に当てはめます。
n |
通る道 | 式に、上の行の答えを当てはめると | func1(n) |
|---|---|---|---|
| 1 | 道A nが2以下 が成り立つ |
計算しない | 1 |
| 2 | 道A 同じく成り立つ | 計算しない | 1 |
| 3 | 道B 成り立たない | 2 × func1(1) + func1(2) = 2 × 1 + 1 |
3 |
| 4 | 道B | 2 × func1(2) + func1(3) = 2 × 1 + 3 |
5 |
| 5 | 道B | 2 × func1(3) + func1(4) = 2 × 3 + 5 |
11 |
n が 1 と 2 の行に式が無いのは、道Aが計算せずに 1 を返すからです。この2行があるから、下の3行が計算できます。
ここが、この表のいちばん大事なところです。n = 4 の行の 2 × 1 + 3 の 3 は、新しく計算した数ではありません ── 1つ上の n = 3 の行で、自分が出した答えです(1 は n = 2 の行の答え)。
式の中の数は、上の行で自分が出した答え
琥珀=この行を読む / 灰=もう読まない
n = 4 の行を作るとき
| n | func1(n) |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
| 4 | ? |
| 5 | ? |
2 × func1(2) + func1(3) = 2 × 1 + 3 = 5
式の func1(2) と func1(3) は琥珀の2行。1 も 3 も、上ですでに出した答えです
1つ下がって、n = 5 の行を作るとき
| n | func1(n) |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 3 |
| 4 | 5 |
| 5 | ? |
2 × func1(3) + func1(4) = 2 × 3 + 5 = 11
さっき作った 5 が、今度は読むほうに回りました。琥珀が1つ下へずれ、n=1・n=2 は、もう読みません(灰)
1行下がるたびに、読む2行が1つ下へずれていく
言い方を1つ決めておきます。「1つ前の値」「2つ前の値」は、いま作ろうとしている値から数えて1つ手前・2つ手前という意味です ── func1(5) を作るときなら 5 と 3、上の図で琥珀だった2行です。
読み取れること
この表を1行ずつ下へ作っていくとき、見るのはすぐ上の2行だけです。読み終えた行は、二度と読みません。
※ func1 をそのまま実行すれば、func1(5) の中から func1(1) や func1(2) も呼ばれます。ここで言っているのは「上の表を作る手順では見なくていい」という意味です。
func1 が呼んでいるのも func1(n - 2) と func1(n - 1) の2つだけで、それより古い値は式に出てきません。n 番目を作るのに要るのは、いつも直前の2つだけ。読む2つに、書き込む場所を1つ足して、箱は3つで足ります。2つ前と、1つ前と、いま作る値 ── func2 が {1, 1, 1} とちょうど3つ持っているのは、これが理由です。
func2 の空欄を、自分で書く
ここがこの問題の背骨です。func2 に注釈を書き込むと、こうなります。
○整数型: func2(整数型: n)
何番目の値がほしいかを n で受け取る
整数型の配列: data ← {1, 1, 1}
箱は3つだけ。ここから増えも減りもしない
整数型: i
for が動かす番号
/* nが3より小さいときは繰返し処理を実行しない */
コメント。実行されない
for (iを3からnまで1ずつ増やす)
3 から n まで。n が2以下なら1周もしない
data[1] ← data[2]
① ずらす ── 2行そろって1つの仕事
data[2] ← data[3]
① ずらす ── 箱の中身を前へ詰める
data[3] ←
② 作る ── ここが空欄
endfor
ここまでが繰り返される
return data[3]
③ 返す ── 最後に作った値
※ 右側の注釈は当サイトで書き加えたものです。プログラム自体は原文のまま引用しています。
くり返しの中は3行で、仕事は2つです。前の2行が「ずらす」、最後の1行が「作る」。空欄は作るほうの1行だけです。作った値は毎周 data[3] に入り、最後に return data[3] で返ります。
はじめの {1, 1, 1} は、後ろの2つが func1(1) と func1(2)(どちらも 1)です。
では、ずらす2行が終わったとき、どの箱に何が入っているのか。数字が初めて別々になる3周目で、1回だけ動かします。
ずらす2行を、3周目で1回だけ動かす
矢印=写す向き(コードの ← と同じ) / 琥珀=写しもと / 緑=いま書き込んだ
ずらす前 ── 3周目のはじめ
data[1]1
data[2]3
data[3]5
data[2] の 3 が2つ前(3番目の値)、data[3] の 5 が1つ前(4番目の値)。data[1] の 1 は、もう使いません
① data[1] ← data[2]
data[1]3
data[2]3
data[3]5
2つ前の 3 を data[1] へ写しました。写しもとの data[2] にも 3 は残っています
② data[2] ← data[3]
data[1]3
data[2]5
data[3]5
1つ前の 5 を data[2] へ写しました。これでずらし終わりです
ずらし終わると、data[1] が2つ前・data[2] が1つ前
ずらしたあと、data[1] が2つ前、data[2] が1つ前。あとは、func1 の最後の行をこの箱の名前で書き直すだけです。
決まりの言葉を、箱の名前に置き換える
① 作りたい値の決まり(func1 の最後の行)
2 × (2つ前の値) + (1つ前の値)
② ずらす2行が終わったあと、その値がいる箱(3周目のようす)
data[1]3
data[2]5
data[3]5
data[1] の 3 が「2つ前」(=3番目の値)、data[2] の 5 が「1つ前」(=4番目の値)。data[3] はこれから書き込む先で、いまは data[2] と同じ 5(=1つ前の値)が残ったままです
③ 置き換える ── これが func2 の空欄に入る式
data[3] ← 2 × data[1] + data[2]
この式で3周目を計算すると 2 × 3 + 5 = 11 ── 物差しの func1(5) と同じ値です。(ここで見たのは3周目だけ。1周目から通して回しても合うかは、あとで確かめます)
同じ形を、解答群から探す
ここで初めて解答群を見ます。探すのは 2 × data[1] + data[2] と同じ形のものです。
解答群(再掲)
ア 2 × data[1] + data[2] ← 書いた式と同じ
イ 2 × data[2] + data[1]
ウ 2 × data[i - 1] + data[i - 2]
エ 2 × data[i - 2] + data[i - 1]
オ data[3] + 2 × data[1] + data[2]
カ data[3] + 2 × data[2] + data[1]
キ data[3] + 2 × data[i - 1] + data[i - 2]
ク data[3] + 2 × data[i - 2] + data[i - 1]
ぴったり同じものは ア の1つだけです ── 8つを見比べて選ぶ、という作業はしていません。先に式を書いたので、解答群は照合するだけで済みました。
答え
正解は ア
func2 の空欄は 2 × data[1] + data[2]。ずらしたあとの data[1] が2つ前、data[2] が1つ前なので、func1 の 2 × func1(n - 2) + func1(n - 1) と同じ形になります。
空欄を埋めた func2 の全体は、こうです。
○整数型: func2(整数型: n)
整数型の配列: data ← {1, 1, 1}
整数型: i
/* nが3より小さいときは繰返し処理を実行しない */
for (iを3からnまで1ずつ増やす)
data[1] ← data[2]
data[2] ← data[3]
data[3] ← 2 × data[1] + data[2]
endfor
return data[3]
1行ずつ追う
この式で本当に func1 と同じ値が出るのかを、1行ずつ動かして確かめます。n = 5 を渡すので、着地するはずの値は func1(5) = 11 です。
見るのは3つの箱の中身と、それぞれが何番目の値を持っているかの2つです。
はじめは箱の中身が どれも 1 なので、数字は変わらないのにラベルだけ書き換わるところがあります。それでいいのです ── 追うのは数字ではなく「その箱がいま何番目の値を持っているか」だからです。ずらす2行が終わると、data[2] と data[3] が同じラベルになるところも見てください。
⚠️ 箱の上の小さな数字(1・2・3)は箱の番号、「◯番目の値」(画面では「変数の状態」の欄)は、その箱が持っている値が1番目から数えて何番目か。同じ「◯番目」でも別のものです。
1行ずつ追う 正解の ア(2 × data[1] + data[2])で n = 5
出典:令和8年度 科目B 公開問題 問3(空欄に ア を入れたもの)
ループ開始前
3つの箱
いま計算していること
変数の状態
return で返す値
トレース表(進めると1行ずつ積み上がります)
選択肢を1つずつ
ここからは答え合わせです。ア を選べた人は読まなくて構いません。
間違いは3種類しかありません。① i を添字に使う(ウ・エ・キ・ク)── 箱は3つなのに、i が 5 になると data[4] を読んでしまう。問題文の「配列の領域外を参照してはならない」に反します。② data[3] + を付ける(オ・カ・キ・ク)── ずらしたあとの data[3] は data[2] と同じ「1つ前の値」なので、1つ前を2回足すことになる。③ 2 × を掛ける相手が逆(イ・ウ・カ・キ)── 2倍するのは「2つ前」= data[1] のほうです。
それぞれが実際に何を作るかは、下の表で確かめてください(物差しは func1 = 3, 5, 11)。
8つ全部の結果を開く
| 選択肢 | n=3 |
n=4 |
n=5 |
何が起きたか |
|---|---|---|---|---|
ア 2 × data[1] + data[2] |
3 | 5 | 11 | 正解。2つ前に 2 × が掛かっている |
イ 2 × data[2] + data[1] |
3 | 7 | 17 | 掛ける先ちがい。n=3 までは正解と同じ |
ウ 2 × data[i - 1] + data[i - 2] |
3 | 9 | 領域外 | i=5 で data[4] を読む |
エ 2 × data[i - 2] + data[i - 1] |
3 | 9 | 領域外 | ウ と掛ける先が逆だが、領域外になる理由は同じ |
オ data[3] + 2 × data[1] + data[2] |
4 | 10 | 28 | 1つ多い。1つ前の値を2回足している |
カ data[3] + 2 × data[2] + data[1] |
4 | 13 | 43 | 1つ多い+掛ける先ちがい |
キ data[3] + 2 × data[i - 1] + data[i - 2] |
4 | 16 | 領域外 | 1つ多い+領域外 |
ク data[3] + 2 × data[i - 2] + data[i - 1] |
4 | 16 | 領域外 | キ と掛ける先が逆。1つ多い+領域外 |
n = 3 では ア も イ も 3 です。周のはじめが {1, 1, 1} で data[1] も data[2] も同じ 1 だから、どちらに 2 × を掛けても変わりません。分かれるのは n = 4 から(ア は 5、イ は 7)。しかも一度ずれると、次の周はそのずれた値を材料にするので、n = 5 では 11 と 17 まで開きます。1つの n で8つ全部を見分けることはできません。
同じ考え方で解く練習問題
身についたかどうかは、作りたい値の決まりが変わった問題で確かめるのがいちばんです。3つの箱の使い方は同じです。
当サイトで作った類題です
f(1) = 1、f(2) = 1、そして3番目からは f(n) = 3 × f(n-1) + f(n-2) で決まる値を作りたいとします。f(n) は「n 番目の値」を表す書き方です(f(3) は 3 × f(2) + f(1) = 3 × 1 + 1 = 4、f(4) は 3 × f(3) + f(2) = 3 × 4 + 1 = 13)。3つの箱 data だけを使って作るとき、空欄に入れる正しい答えはどれですか。
○整数型: func3(整数型: n)
整数型の配列: data ← {1, 1, 1}
整数型: i
for (iを3からnまで1ずつ増やす)
data[1] ← data[2]
data[2] ← data[3]
data[3] ←
endfor
return data[3]
「箱を持ち回る」問題を見分ける
くり返しの中に「ずらす代入」と「作る代入」が並んでいたら、この形です。見つけたら、次の順で読みます。
| 見るところ | 読み取ること |
|---|---|
| ずらす代入の向き | どの箱が古いほうになるか。data[1] ← data[2] なら data[1] が古い側です |
| 作る代入で読む箱 | ずらしたあとの役割(2つ前か、1つ前か)で決める。くり返しの回数 i を添字に持ち込みません(箱の数が固定なので、すぐ外に出ます)。配列そのものを端から動かす問題(令和8年度の問1など)では、逆に i を使います |
ほかの問題でも、この3つを外さない
- 決まりは、箱の名前を使わずに書く。
本問は
func1の最後の行がそのまま決まりでした。隣に関数が無い問題なら、問題文の日本語から起こします ── 「3番目からは、直前2つを足して2倍した値」なら2 × ((1つ前の値) + (2つ前の値))。先に箱の名前で書くと、②(ずらし終えた時点で、どの箱が何を持っているかを見る段)を飛ばしたことになります。 - 役割がどの箱にいるかは、「ずらし終えた時点」で見る。
data[1] ← data[2] data[2] ← data[3]
空欄の行だけを見ても決まりません。上のずらす代入を全部実行し終えた状態で見ます ── 1行でも手前で見ると、data[1]はまだ前の周の値です。 - 箱が増えても、やることは同じ。
3つ前までさかのぼる決まりなら箱は4つ、ずらす代入は3行。終わったあとは
data[1]が3つ前・data[2]が2つ前・data[3]が1つ前で、いちばん後ろの箱が、いつも「これから書く値」です。
解答群を見るのは、式を書き終えたあと。先に見ると、8つのどれかを正解だと思い込んだまま理由をさがすことになり、時間だけが減ります。※ この手順はIPAが示したものではなく、当サイトでまとめたものです。
「ずらす」の向きにも決め方があります。ここは前へ詰めるので前の箱から順に、後ろへずらすなら後ろの箱から順に ── 逆に書くと、まだ使う値を先に上書きしてしまいます。この向きそのものが問われているのが令和8年度の問1です。
次に読む
この問題でどこに手間取ったかで、行き先が変わります。
data[1] ← data[2] のどちらが書かれるかが曖昧だった人へG5選択処理 if ── if 〜 endif の範囲でつまずいた人へ一覧科目B 全44問の解説 ── 同じ形の問題を続けて解きたい人へこの記事で引用した資料
いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。
「f(n) = 3 × f(n-1) + f(n-2)」の練習問題は当サイトのオリジナルです。

