令和8年度 基本情報技術者試験 科目B 問3の解説|3つの箱を持ち回る

基本情報技術者試験

令和8年度 科目B 公開問題 問3擬似言語・再帰・繰返し最終更新 2026-09-03

令和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 のような番号は、当サイトの擬似言語の教科書の第何回かを表します)。

まず、できあがりを見る ── 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つの箱

▲ いま読んでいる▲ いま書いた

いま計算していること

まだ計算していません

変数の状態

トレース表(進めると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つ多い+領域外
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つを外さない

  1. 決まりは、箱の名前を使わずに書く。
    本問は func1 の最後の行がそのまま決まりでした。隣に関数が無い問題なら、問題文の日本語から起こします ── 「3番目からは、直前2つを足して2倍した値」なら 2 × ((1つ前の値) + (2つ前の値))。先に箱の名前で書くと、②(ずらし終えた時点で、どの箱が何を持っているかを見る段)を飛ばしたことになります。
  2. 役割がどの箱にいるかは、「ずらし終えた時点」で見る。
    data[1] ← data[2]
    data[2] ← data[3]
    空欄の行だけを見ても決まりません。上のずらす代入を全部実行し終えた状態で見ます ── 1行でも手前で見ると、data[1] はまだ前の周の値です。
  3. 箱が増えても、やることは同じ。
    3つ前までさかのぼる決まりなら箱は4つ、ずらす代入は3行。終わったあとは data[1] が3つ前・data[2] が2つ前・data[3] が1つ前で、いちばん後ろの箱が、いつも「これから書く値」です。

解答群を見るのは、式を書き終えたあと。先に見ると、8つのどれかを正解だと思い込んだまま理由をさがすことになり、時間だけが減ります。※ この手順はIPAが示したものではなく、当サイトでまとめたものです。

「ずらす」の向きにも決め方があります。ここは前へ詰めるので前の箱から順に、後ろへずらすなら後ろの箱から順に ── 逆に書くと、まだ使う値を先に上書きしてしまいます。この向きそのものが問われているのが令和8年度の問1です。

次に読む

この問題でどこに手間取ったかで、行き先が変わります。

この記事で引用した資料

いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。

「f(n) = 3 × f(n-1) + f(n-2)」の練習問題は当サイトのオリジナルです。

Copied title and URL