気づけば解けるのは1点 ── bins[data[i]] ← data[i] は、値を、その値と同じ番号の枡へ置いています。そこが読めると、条件の「昇順」はひとりでに満たされ、残るのは未定義が残らないかだけになります。
難易度 ★(当サイトの目安)── 値が重ならず1〜6に収まる入力を選ぶだけ。4段階の決め方は科目B 最短合格の戦略にあります。
出題
出典:基本情報技術者試験 科目B サンプル問題 問11
次の記述中の に入れる正しい答えを,解答群の中から選べ。ここで,配列の要素番号は1 から始まる。
関数binSort をbinSort( ) として呼び出すと,戻り値の配列には未定義の要素は含まれておらず,値は昇順に並んでいる。
〔プログラム〕
○整数型の配列: binSort(整数型の配列: data)
整数型: n ← dataの要素数
整数型の配列: bins ← {n個の未定義の値}
整数型: i
for (i を 1 から n まで 1 ずつ増やす)
bins[data[i]] ← data[i]
endfor
return bins
解答群
ア {2, 6, 3, 1, 4, 5} / イ {3, 1, 4, 4, 5, 2}
ウ {4, 2, 1, 5, 6, 2} / エ {5, 3, 4, 3, 2, 6}
※ 解答群の原本は ア〜エ を2つの列に分けて並べた形です。当サイトでは2行にまとめて引用しました(字句は変えていません)。
答えだけ先に見る
正解は ア({2, 6, 3, 1, 4, 5})です。
この問題に出てくる記号
読めない記号があったときだけ開いてください。
擬似言語の記号 6コ の読み方をひらく
| 書き方 | 読み方 |
|---|---|
○整数型の配列: binSort(整数型の配列: data) |
ここから関数 binSort が始まるという印。整数の配列を1つ受け取って data と名前を付け、整数の配列を1つ返します |
整数型: n ← dataの要素数 |
整数の箱 n を用意し、data に入っている値の個数を入れる。← は右の値を左の箱へ入れるという印です |
整数型の配列: bins ← {n個の未定義の値} |
整数の配列 bins を用意する。枡は n 個で、どの枡にもまだ値が入っていない(=未定義の)状態です |
data[i] bins[data[i]] |
配列 data の i 番目の値/角括弧の中には式を書けます。bins[data[i]] は先に data[i] を計算して、その値を番号として bins を引く、と内側から読みます |
for (i を 1 から n まで 1 ずつ増やす) |
i を 1, 2, 3 … と n まで変えながら、endfor までをくり返す |
return bins |
配列 bins を戻り値として返して、ここで終わり |
コードは何をしているか ── 値を、その値と同じ番号の枡へ置く
行数は8行、くり返しの中は1行だけです。どの行が何をしているかを先に見ておきます。
○整数型の配列: binSort(整数型の配列: data)
整数の配列を1つ受け取り、整数の配列を1つ返す
整数型: n ← dataの要素数
受け取った配列の個数を n に入れる
整数型の配列: bins ← {n個の未定義の値}
返すための配列。枡は n 個で、まだどこにも値が入っていない
整数型: i
くり返しで使う箱
for (i を 1 から n まで 1 ずつ増やす)
data の 1番目から n 番目まで、順に見ていく
bins[data[i]] ← data[i]
ここが唯一の書き込み。この行を1回ぶん動かせば、bins の作られ方が分かる
endfor
くり返しの終わり
return bins
返すのは bins。問題文の条件は、この配列についての話
※ 右側の注釈は当サイトで書き加えたものです。プログラム自体は原文のまま引用しています。
返すのは bins です。問題文は、その bins について「未定義の要素は含まれておらず,値は昇順に並んでいる」と言っています。つまり、最後の bins がそうなるように data を選べ、ということです。
では bins はどう作られるのか。書き込む行は bins[data[i]] ← data[i] の1か所だけなので、この行を1回ぶん動かせば分かります。data に ア の {2, 6, 3, 1, 4, 5} を渡して、1周目を見ます。
ア {2, 6, 3, 1, 4, 5} を渡して、くり返しの1周目だけ動かす
琥珀=いま読んでいる枡 / 緑=ここまでに書き込まれた枡 / 網掛け=未定義(まだ何も入っていない) / 灰=もう読んだ枡 / 緑の矢印=値が移る先
① i が 1。data[1] を読んで、書く枡の番号を決める
bins
1未定義
2未定義
3未定義
4未定義
5未定義
6未定義
bins の 2 番へ
data
12
26
33
41
54
65
bins[data[i]] は内側から読みます。data[1] は 2 なので、この行は bins[2] ← 2。書く枡は、1番目でも i 番目でもなく、読んだ値と同じ番号の枡です。
② 書いたあと
bins
1未定義
22
3未定義
4未定義
5未定義
6未定義
data
12
26
33
41
54
65
入れた値は 2、入れた枡の番号も 2。bins[data[i]] ← data[i] は、枡の番号にも、入れる値にも、同じ data[i] を使っています。
置く場所を決めるのは、並んでいる順番ではなく値そのものです。
値 v は、いつでも bins の v 番目に入ります。ということは、1番目には 1、2番目には 2、… しか入りません。もし枡が全部埋まったなら、その並びは {1, 2, 3, 4, 5, 6} ── 昇順以外にはなりようがありません。2つの条件のうち「値は昇順に並んでいる」のほうは、未定義の枡が1つも残らなければ、ついてきます。
残る条件は未定義の要素が残らないことのほう。これだけが、渡す配列を選び分けます。
未定義が残らない配列を決める
〔プログラム〕枡を作るところと、書き込むところ
整数型の配列: bins ← {n個の未定義の値}
整数型: i
for (i を 1 から n まで 1 ずつ増やす)
bins[data[i]] ← data[i]
endfor
※ 上の〔プログラム〕からの抜粋です(1字も変えていません)。
bins の枡は n 個で、for は i を 1 から n まで動かすので、書き込みは n 回です。解答群はどれも要素数が 6 なので、6つの枡に、6回書き込むことになります。ちょうど同じ数です。
ということは、6つの枡を全部埋めるには毎回ちがう枡に書くしかありません。書く枡の番号は値そのものでしたから、同じ値が2回出てくると、2回とも同じ枡に書くことになります。ア以外の選択肢で、それがどうなるかを見ます。
イ {3, 1, 4, 4, 5, 2} を渡すと、6回書いても枡が1つ余る
琥珀の破線=これから読む2つの枡 / 緑=ここまでに書き込まれた枡 / 網掛け=未定義(まだ何も入っていない) / 灰=もう読んだ枡 / 緑の矢印=値が移る先
① 2周目まで終わったところ ── 3周目と4周目は、どちらも data[i] が 4
bins
11
2未定義
33
4未定義
5未定義
6未定義
どちらも bins の 4 番へ
data
13
21
34
44
55
62
1周目の 3 は bins[3] へ、2周目の 1 は bins[1] へ入りました。次の3周目は bins[4] ← 4。その次の4周目も data[4] が 4 なので、また同じ bins[4] に、同じ 4 を書きます。2回書いても枡の中身は変わらないので、6回の書き込みのうち1回が、むだになります。
② 6周まわり終わったところ
bins
11
22
33
44
55
6未定義
data
13
21
34
44
55
62
緑は5つ。6回書いたのに、埋まった枡は5つしかありません。bins[6] に 6 が入る回は、一度も来ませんでした ── data に 6 が1つも入っていないからです。戻り値に未定義の要素が残るので、イ は条件に合いません。
枡は6つ、書き込みも6回。同じ値が2回出た時点で、どこかの番号は最後まで空のままです。
渡す配列に求められるのは、これで出そろいました。値はどれも 1 から 6 のあいだ(枡は6つしかないので、これを外れると書く枡がありません)、値は6個、同じ値が2回出てこない。1 から 6 の6種類から、重ならないように6個選ぶのですから、6種類が1つずつ全部使われるしかありません。
空欄に入るのは、1 から 6 までが1回ずつ並んだ配列です。
解答群を見る
同じ値が2回出てこないものを探します。
| 選択肢 | 2回出てくる値 | 出てこない値 | 戻り値 |
|---|---|---|---|
ア {2, 6, 3, 1, 4, 5} |
なし | なし | {1, 2, 3, 4, 5, 6} |
イ {3, 1, 4, 4, 5, 2} |
4 | 6 | {1, 2, 3, 4, 5, 未定義} |
ウ {4, 2, 1, 5, 6, 2} |
2 | 3 | {1, 2, 未定義, 4, 5, 6} |
エ {5, 3, 4, 3, 2, 6} |
3 | 1 | {未定義, 2, 3, 4, 5, 6} |
ア だけが 1 から 6 までを1回ずつ持っています。
答え合わせ
正解は ア {2, 6, 3, 1, 4, 5}。戻り値は {1, 2, 3, 4, 5, 6} になります。
イ・ウ・エ は、2回出てくる値のぶんだけ書き込みが重なるので、上の表のとおり戻り値に未定義が1つ残ります。この問題で見るのは、2つの条件のうち未定義のほうだけでした ── 未定義さえ残らなければ、昇順は置き方から必ず成り立つからです。
アを入れて、最後まで動かします。
1行ずつ追う 正解の ア で binSort({2, 6, 3, 1, 4, 5})
出典:科目B サンプル問題 問11(空欄に ア を入れたもの)
ループ開始前
配列
いま計算していること
変数の状態
return で返した値
トレース表(進めると1行ずつ積み上がります)
次に読む
この問題でどこに手間取ったかで、行き先が変わります。
この記事で引用した資料
いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。

