令和8年度 基本情報技術者試験 科目B 問1の解説|配列を1つずつ後ろへずらす

基本情報技術者試験

令和8年度 科目B 公開問題 問1擬似言語・配列・繰返し最終更新 2026-08-29

令和8年度の科目B、その1問目です。科目Bのプログラムは擬似言語(特定のプログラミング言語ではなく、IPAが試験用に定めた書き方)で書かれます。この問題は8行しかなく、出てくるのは配列と繰返しだけ(どちらも、このあとの「この問題を解くのに要る文法」の節で説明します)。それでも空欄をどれにするか迷うのは、問われているのが「どう書くか」ではなく「繰返しをどちら向きに動かすか」だからです。ここでは、その1文字を自分で決められるところまで、1行ずつ確かめていきます。

出題

まず原文のまま読んでみてください。記号(←、[ ]、for)の読み方は、動画の次の「この問題を解くのに要る文法」の節にまとめてあります。読めなくてもここでは問題ありません。

出典:令和8年度 基本情報技術者試験 科目B 公開問題 問1

次のプログラム中の に入れる正しい答えを,解答群の中から選べ。ここで,配列の要素番号は1 から始まる。

次のプログラムは,整数型の配列data の末尾の要素の値を先頭の要素に移動する。この際,末尾以外の各要素の値は,一つずつ後ろの要素に移動する。

〔プログラム〕

整数型の配列: data ← {1, 2, 3, 4, 5, 6, 7, 8, 9}
整数型: top, i
整数型: len ← dataの要素数
top ← data[len]
for (i を )
  data[i] ← data[i - 1]
endfor
data[1] ← top

解答群

ア 2 から len - 1 まで 1 ずつ増やす

イ 2 から len まで 1 ずつ増やす

ウ len - 1 から 2 まで 1 ずつ減らす

エ len から 2 まで 1 ずつ減らす

答えだけ先に見る

正解は エ(len から 2 まで 1 ずつ減らす)。決め手は2つだけです ── 後ろから前へ回すことと、len から始めること。

まず、通しで見る

4分17秒の動画です(音声つき)。この空欄を自分で決められるようになります。向きで2つ、端で1つと2手で絞るところを、配列を実際に動かしながら確かめます。

後半は8周ぜんぶを省かずに追い、最後に4つの選択肢それぞれの結果を並べます。自分が選んだものがどこで違ったのかまで分かります。

動画で追いかけるのは、上の8行です。

向きと端を2手で決める(4分17秒・音声つき)

再生できないときは、この下の説明とトレースで同じ内容を追えます。

ここから、同じ内容を1つずつ確かめていきます。

この問題を解くのに要る文法

いま読めればいいのは、7つだけです。細かいところは、使う場面で足していきます。

書き方 読み方
← 左に書き込む。top ← data[9] なら「9番目を読んで top に書く」。書かれた側の元の値は消える
data[3] data の3番目。配列の1つ分を、この記事では「マス」と呼びます
data[i - 1] [ ] の中は計算してよい。i より1つ小さい番号=1つ前のマス
dataの要素数 マスの個数。{1, 2, …, 9} なら 9
整数型: 整数だけを入れる箱を用意する、という宣言。整数型の配列: ならその箱がマスの列になる
for 〜 endfor はさまれた行を、何回も実行する。1回ぶんを「1周」、全体を「ループ」と呼びます
◯ から ◯ まで
1 ずつ増やす
くり返しの回数の決め方。3 から 6 まで 1 ずつ増やす なら i が 3, 4, 5, 6 と変わりながら1周ずつ実行します(始まりも終わりも含む)。1 ずつ減らす なら 6, 5, 4, 3 と逆に動きます

これで手が止まるところがあれば、下の教科書から先にそこだけ拾ってきてください。G4-1 のような番号は当サイトの教科書の回の番号で、G が第1部(擬似言語)、A が第2部(アルゴリズム)です。

まず、できあがりを見る

いきなり1行ずつ追うと、何を目指しているのか分からないまま数字を書き写す作業になります。先に、このプログラムが終わったときの姿を見ておきます。

問題文が言っているのは2つです。「末尾の要素の値を先頭の要素に移動する」と、「末尾以外の各要素の値は,一つずつ後ろの要素に移動する」。data は {1, 2, 3, 4, 5, 6, 7, 8, 9} なので、こうなります。

はじめの data と、終わったあとの data

問題文が言っているのは、この形

はじめの data

11

22

33

44

55

66

77

88

99

終わったあと

19

21

32

43

54

65

76

87

98

斜めの矢印は8本とも同じことを言っています ── その値が、1つ右の席へ動く。琥珀の1本は押し出された 9 で、これだけが下をくぐって、いちばん左へ回り込みます

数が減ることも増えることもありません。8個は席を1つずつ右へずれ、押し出された 9 がいちばん左へ回り込んだだけです。

「後ろ」は、番号が大きいほう

data[1] が先頭、data[9] が末尾です。「一つずつ後ろの要素に移動する」=「要素番号が1つ大きいところへ移す」ということ。上の図の短い矢印が8本とも右を向いているのは、そのためです。ここで前後を取り違えると、以降の判断が全部ひっくり返ります。

プログラムは3つの部分でできている

8行を上から順に読むと長く見えますが、やっていることは3つです。同じプログラムに、その3つを書き込むとこうなります。

1整数型の配列: data ← {1, 2, 3, 4, 5, 6, 7, 8, 9}

動かす対象。要素は9個

2整数型: top, i

top = 値を1つよけておく箱/i = for が動かす要素番号

3整数型: len ← dataの要素数

len = 9 ── マスの個数が、そのまま入る

4top ← data[len]

① 退避 ── 末尾の 9 を、先に手元へ取っておく

5for (i を )

② ずらす ── 空欄が決めるのは、この範囲だけ

6 data[i] ← data[i - 1]

読むのは1つ前、書くのはいまの場所。この向きが空欄を決める

7endfor

ここまで来たら5行目に戻り、次の i で6行目をやり直す

8data[1] ← top

③ 戻す ── よけておいた 9 を、先頭へ入れる

※ 左の行番号と右の注釈は当サイトで付けたものです(原文にはありません)。プログラム自体は原文のまま引用しています。以降、本文で「6行目」と言うときはこの番号を指します。

最初の3行は準備です。値を入れる箱を用意しています。整数型: top, i のように ← が無ければ箱を作るだけ(中身はまだ空)、整数型: len ← dataの要素数 のように ← が続いていれば箱を作って値も入れる、と読みます。

ここで len が 9 に決まります。dataの要素数はマスの個数のことなので、端から端まで数えるだけです。

len に入るのは、マスの個数

3行目 整数型: len ← dataの要素数

data のマスは、いくつあるか

11

22

33

44

55

66

77

88

99

灰色の矢印は範囲です(値が動くわけではありません)。いちばん左の 1 番から、いちばん右の 9 番まで、マスは 9個

その個数が、そのまま len に入る

整数型: len ← dataの要素数

3行目を実行したあと

len9

len は箱です(マスの列ではありません)。配列のマスとは形を変えてあります

len = 9。解答群の ア〜エ は4つとも len で書かれているので、9 に置き換えて読む

箱の名前 top について

名前は原文のままです。top に入るのは末尾の値なので、名前と中身がずれて見えます。名前ではなく、「どの行で入れて、どの行で使うか」で読んでください ── 4行目で入れて、8行目で先頭に出す箱です。

そのあとが本体で、① 退避 → ② ずらす → ③ 戻すの3段構えです。空欄があるのは②の範囲指定だけで、①と③は空欄がどれになっても変わりません。

空欄が決めるのは、たった2つ

ここから自分で絞ります。解答群の4つを、そのまま4つとして比べる必要はありません。

len は 9 でした。4つの選択肢を、i が実際にとる値に書き下すと、こうなります。◯ から ◯ まで は両端を含みます(「9 から 2 まで」なら 9 も 2 も実行されます)。

選択肢 i が実際にとる値(len = 9)
ア 2 から len - 1 まで 1 ずつ増やす 2, 3, 4, 5, 6, 7, 8
イ 2 から len まで 1 ずつ増やす 2, 3, 4, 5, 6, 7, 8, 9
ウ len - 1 から 2 まで 1 ずつ減らす 8, 7, 6, 5, 4, 3, 2
エ len から 2 まで 1 ずつ減らす 9, 8, 7, 6, 5, 4, 3, 2

数字に直すと、4つの違いは2点しかないと分かります。i が増えるか減るか(向き)と、9 を含むか 8 で止まるか(端)です。しかも片方ずつ決められます。

手順1 ── 向きは「後ろから前へ」

data[i] ← data[i - 1] で読まれるのは data[i - 1]、書かれるのは data[i] です。読むほうが1つ小さい番号にあります。

ということは、どちら向きに回すかで、読む相手が変わります。最初の2周を並べてみます(ここで見るのは向きだけです。端はまだ決めていないので、減らす側はとりあえず 9 から始めた場合で書きます ── 始まりが 8 でも、この節で見る「読む相手」は変わりません)。

前から回したら(i を 2, 3, … と増やす)

矢印は値の動き。どちらの図も右向きなのは、6行目が小さい番号を読んで大きい番号に書くからです。変わるのは i の進む向きだけ ── ここでは i は 2 → 3 → 4 … と右へ進みます

1周目 i = 2 data[2] ← data[1]

実行する前

11

22

33

44

55

66

77

88

99

実行したあと

11

21

33

44

55

66

77

88

99

読んだ data[1] は、まだ書き換えていないマス。でも書き込む先の data[2] に入っていた 2 は、まだどこへも運んでいませんでした。上から 1 を書いた時点で、その 2 は消えます

2周目 i = 3 data[3] ← data[2]

実行する前
(2番目は1周目で
1 に変わっている)

11

21

33

44

55

66

77

88

99

実行したあと

11

21

31

44

55

66

77

88

99

読んだのは、1周目で 1 に化けたマス。運びたかった 2 はもう無いので、1 をもう一度運ぶことになります

読む前に、その値を自分で踏みつぶしている

後ろから回したら(i を 9, 8, … と減らす)

プログラムは同じ。i だけが 9 → 8 → 7 … と左へ戻ります(矢印が右向きなのは、上の図と同じく値の動きだからです)

1周目 i = 9 data[9] ← data[8]

実行する前

11

22

33

44

55

66

77

88

99

実行したあと

11

22

33

44

55

66

77

88

98

読んだ data[8] は、まだ書き換えていないマス。書き込む先の data[9] にあった 9 は、4行目で top によけたあとなので、上から書いても失われません

2周目 i = 8 data[8] ← data[7]

実行する前
(9番目は1周目で
書き換わっている)

11

22

33

44

55

66

77

88

98

実行したあと

11

22

33

44

55

66

77

87

98

ここも、読んだ data[7] はまだ書き換えていないマス。書き込む先の data[8] は、1周目でもう読み終えたあとです

書き込む先は、いつも もう用が済んだマス(読み終えたか、よけ終わったか)

向きの結論

後ろから前へ(= i を減らす)。これでウ と エ の2つに絞れました。ア と イ は、この時点で消えます。

手順2 ── 端は「len から」「2 まで」

残った ウ と エ の違いは、始まりが 8 か 9 かだけです(終わりはどちらも 2)。ここはi に端の値を入れて、6行目が実際に触るマスを書き出すと決まります。

i 6行目が触るマス どうなるか
9(len) data[9] ← data[8] 末尾にも書き込める。ここから始める
8(len - 1) data[8] ← data[7] ここから始めると、9番目に誰も書かないまま終わる
2 data[2] ← data[1] 読む data[1] は存在する。ここで止める
1 data[1] ← data[0] data[0] は存在しない。1 まで行ってはいけない

端の結論

len から 2 まで。始まりを1つ手前にすると末尾に誰も書かず、終わりを1つ先まで行かせると存在しないマスを読みます。向きと合わせて、エ が残りました。

ほかの問題でも、この順で決める

  1. 先に向きを決める。6行目がどちらを読んで、どちらに書くかを見ます。data[i] ← data[i - 1] は「小さい番号を読んで、大きい番号に書く」。まだ読んでいないマスを、先に書きつぶさない向きを選びます。
  2. 次に端を決める。書き込む必要があるマスが1つでも漏れていないか(=端が1つ手前で止まっていないか)と、読む側が配列からはみ出していないか。この2つだけを見ます。

この順なら、4択が「向きで2つ → 端で1つ」と2手で絞れます。4つを1つずつ最後まで追うのは、時間の使い方として損です。

なぜ4行目で、末尾をよけておくのか

top ← data[len] は、末尾の値 9 を top という箱に写しておく行です。この1行が何のためにあるのかを、先に確かめておきます。

向きと端が決まったので、i は 9, 8, 7, 6, 5, 4, 3, 2 と動きます。つまり最初の周で i が 9 になり、末尾のマスに書き込みます。もしこの1行が無かったらどうなるかを、動かす前に確かめておきます。

追いかける前に、ひとつ予想してみましょう

次のプログラムには、末尾の値をよけておく行がありません(top に値を入れる行が1つも無い)。最後まで実行し終えたとき、先頭の data[1] には何が入っていますか。

整数型の配列: data ← {1, 2, 3, 4, 5, 6, 7, 8, 9}
整数型: top, i
整数型: len ← dataの要素数
for (i を len から 2 まで 1 ずつ減らす)
  data[i] ← data[i - 1]
endfor
data[1] ← top

i が 9 になる周では、この行は data[9] ← data[8] です。末尾の 9 は、そこで上書きされて消えます。ところが最後の8行目では、その 9 を先頭に入れなければなりません。消えたあとで取りに行っても、もうどこにもないのです。

だから4行目がある

top ← data[len] は、これから壊れる場所の値を、壊れる前に別の箱へ写しておく行です。top に入れた 9 は配列の外にあるので、data をどれだけ書き換えても無事です。

この「先に取っておく」書き方は、値を入れ替える処理で何度も出てきます。上書きされると困る値は、上書きが始まる前によける ── 科目Bで繰り返し問われる型です。

1行ずつ追う

ここまでの結論を、実際に動かして確かめます。本番で毎回8周ぶんを追う必要はありませんが、いちど全部見ておくと、次からは端だけ確かめれば済むようになります。

配列のマスの下には ▲ が出ます ── 薄い色がいま読んでいるマス、濃い色がいま書いたマス。読み書きが両方ある6行目では2つ、片方だけの行では1つ、どちらもしない行では出ません。見るのは ▲ がどこを指しているかと、書き込む先が、いつも「もう用済みの場所」になっているかの2点です。

箱の欄の — はその行をまだ実行していない(箱がまだ無い)、未定義 は箱はできたが値が入っていないという意味です。

トレースシミュレータ 正解の エ で最後まで追う

出典:令和8年度 科目B 公開問題 問1(空欄に エ を入れたもの)


ループ開始前

配列

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

いま計算していること

まだ計算していません

変数の状態

トレース表(進めると1行ずつ積み上がります)

前から回すと、どうなるか

「後ろから」でなければいけない理由は、前から回したものを見るのがいちばん早いです。空欄に イ(2 から len まで 1 ずつ増やす)を入れて、同じプログラムを動かしてみます。最初の3行は正解のときとまったく同じなので、シミュレータは4行目から始めます。

動かす前に、ひとつ予想してみましょう

次のプログラムでは、繰返しを「2 から len まで 1 ずつ増やす」=前から後ろへ動かします。繰返しが終わって endfor を抜けたとき(プログラム最終行の data[1] ← top を実行する前)の data はどうなっていますか。

整数型の配列: data ← {1, 2, 3, 4, 5, 6, 7, 8, 9}
整数型: top, i
整数型: len ← dataの要素数
top ← data[len]
for (i を 2 から len まで 1 ずつ増やす)
  data[i] ← data[i - 1]
endfor
data[1] ← top

トレースシミュレータ イ(前から回す)だとどうなるか

出典:令和8年度 科目B 公開問題 問1(空欄に イ を入れたもの)


ループ開始前

配列

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

いま計算していること

まだ計算していません

変数の状態

トレース表(進めると1行ずつ積み上がります)

結果は「少しずれた形」にならない

向きを間違えると、値が1つずつずれるのではなく、先頭の値で全部が塗りつぶされます。惜しい形ではなくまったく違う形になるのが、この誤りの見分けどころです。逆にいえば、同じ値が並んだ答えが出たら、向きを疑えばよいということです。

答え

正解は エ

for (i を len から 2 まで 1 ずつ減らす)。終了時の data は {9, 1, 2, 3, 4, 5, 6, 7, 8} で、冒頭で先に見た「できあがり」と同じ形です。

選択肢を1つずつ

誤答の3つは、向きを違えた イ、端を違えた ウ、両方を違えた アの3通りです。自分が選んだものから、どちらでつまずいたかが分かります。

選択肢 終了時の data 何が起きたか
ア 2 から len - 1 まで 1 ずつ増やす {9, 1, 1, 1, 1, 1, 1, 1, 9} 向きも端も違う。前から回したので2番目以降が 1 で塗りつぶされ、さらに i が 8 で止まるので 9番目には誰も書かず、元の 9 が残ります
イ 2 から len まで 1 ずつ増やす {9, 1, 1, 1, 1, 1, 1, 1, 1} 向きが違う。端は正しいのに、前から回したせいで読む場所を自分で先に潰します
ウ len - 1 から 2 まで 1 ずつ減らす {9, 1, 2, 3, 4, 5, 6, 7, 9} 端が違う。向きは正しく、エの1周目(data[9] ← data[8])を丸ごと飛ばした形です。2周目以降はエと同じ動きなので、9番目に誰も書き込まず、元の 9 がそのまま残ります。いちばん惜しい誤りで、末尾を見ないと正解と区別がつきません
エ len から 2 まで 1 ずつ減らす {9, 1, 2, 3, 4, 5, 6, 7, 8} 正解。後ろから回すので、書き込む先はつねに用済みの場所。len から始めるので9番目も更新されます
ウ と エ の見分け方

この2つは末尾(9番目)だけが違います。9 が2つある形が出たら、端を1つ手前で止めている ── 元の値が生き残っている=そこに誰も書き込んでいない、と読んでください。最初の1周だけ試せば決まります。

同じ形の練習問題

身についたかどうかは、読む位置が、書く位置の「前」ではなく「後ろ」にある問題で確かめるのがいちばんです。しかも今度は、触ってはいけないマスが1つあります。向きも端も、自分で決めてみてください。

当サイトオリジナルの類題です。今度は2番目の要素の値を末尾へ移し、3番目から末尾までの各要素の値は一つずつ前へ移します。1番目はそのままです({10, 20, 30, 40, 50} が {10, 30, 40, 50, 20} になります)。よけておく箱には tmp という名前を付けました。空欄に入れる正しい答えはどれですか。

整数型の配列: data ← {10, 20, 30, 40, 50}
整数型: tmp, i
整数型: len ← dataの要素数
tmp ← data[2]
for (i を )
  data[i] ← data[i + 1]
endfor
data[len] ← tmp

「ずらす」問題を見分ける

答え合わせは、上の練習問題で選んだあとに出る解説を見てください。ここでは、ほかの問題で同じ形に出会ったときの見分け方をまとめます。ここまで使った判断のうち、向きと読む側がはみ出す端は、くり返しの中身1行を見るだけで決まります(もう一方の端は、「どこからどこまで動かすのか」を問題文から読み取って決めます)。読む側が前にあるか後ろにあるかで、回す向きがそっくり裏返ります。

くり返しの中身 i の動く向き 読む側がはみ出す端
data[i] ← data[i - 1]
1つ小さい番号を読む
後ろから前へ
(i を減らす)
小さい側
data[0] を読みそうになる
data[i] ← data[i + 1]
1つ大きい番号を読む
前から後ろへ
(i を増やす)
大きい側
data[len + 1] を読みそうになる

ループの外でよけておく値は、どちらの形でもいちばん最初に書き込むマスの値です(この問題なら、最初に書き込むのが data[len] なので末尾の 9)。そこは1周目で上書きされるので、始まる前に取り出しておくしかありません。

ここでi の動く向きと、値が動く向きは逆になります。上の行は i を後ろから前へ動かしますが、値は1つ後ろへずれます。下の行はその逆です。混ざりやすいので、動かしているのが i なのか値なのかを、そのつど確かめてください。

そもそも「ずらす問題だ」と見抜く合図は、くり返しの外側にある2行です。ループの前に ◯ ← data[…]、ループの後に data[…] ← ◯ があれば、それは押し出される値をよけて、あとで戻す形。よけた値がどこへ戻るかを先に読めば、向きも端も逆算できます。

次に読む

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

この記事で引用した資料

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

「2番目の要素を末尾へ移す」練習問題は当サイトのオリジナルです。

Copied title and URL