新・基本情報 科目 B アルゴリズムとプログラミング サンプル問題 解説 1


2022-07-06 更新

2023 年 4 月から基本情報技術者試験の制度が変更され、特に科目 B 試験(従来の午後試験に該当するもの)の内容が大きく変わります。 この記事では、 IPA (独立行政法人情報処理推進機構)が公開している「基本情報技術者試験 科目 B のサンプル問題」の中から、アルゴリズムとプログラミングの問題を取り上げ、従来からの変更点を説明します。

サンプル問題(問 1 ) 新たな分岐構文 if

アルゴリズムとプログラミングの問題は、

  1. 「プログラムの基本要素(型、変数、配列、代入、算術演算、比較演算、論理演算、選択処理、繰返し処理、手続・関数の呼出し、など)」
  2. 「データ構造及びアルゴリズム(再帰、スタック、キュー、木構造、グラフ、連結リスト、整列、文字列処理、など)」
  3. 「プログラミングの諸分野への適用(数理・データサイエンス・ AI などの分野を題材としたプログラム、など)」

という 3 つのカテゴリに分けられています。

サンプル問題の問 1 は「プログラムの基本要素」の問題です。出題趣旨は、

「年齢によって決まる施設の入場料を返す処理を題材として、与えられた仕様を満たす選択処理を可能にする条件式を導く能力を問う」

です。 以下に、問題を示します。

プログラムの基本要素

問 1

次のプログラム中のに入れる正しい答えを,解答群の中から選べ。

ある施設の入場料は,0 歳から 3 歳までは 100 円,4 歳から 9 歳までは 300 円,10 歳以上は 500 円である。関数 fee は,年齢を表す 0 以上の整数を引数として受け取り,入場料を返す。

〔プログラム〕

○整数型: fee(整数型: age)
 整数型: ret
 if (age が 3 以下)
   ret ← 100
 elseif (  )
   ret ← 300
 else
   ret ← 500
 endif
 return ret

解答群

(age が 4 以上) and (age が 9 より小さい)
(age が 4 と等しい) or (age が 9 と等しい)
(age が 4 より大きい) and (age が 9 以下)
age が 4 以上
age が 4 より大きい
age が 9 以下
age が 9 より小さい

プログラムの内容は、擬似言語で示されていますが、従来の試験の擬似言語と比べて記述形式が変わっています

従来は、分岐(選択)と繰り返しが などの図形で示されていましたが、それが ifwhilefor などの言葉に変わっています。 英語としてプログラムを読めるので、わかりやすくなったといえるでしょう。 従来は、処理の先頭に (ドット)がありましたが、新たな擬似言語にはありません。 ただし、変数への代入は、従来と同じであり で示します。

 

プログラムの内容を説明しましょう。

年齢を表す整数型の引数 age を受け取り、戻り値として年齢に応じた入場料を返す fee 関数が定義されています。 関数の定義に を付けることは従来と同じですが、変数(ここでは変数 ret )の宣言には従来と異なり を付けません。 このような細かな変更は、あまり気にする必要はないでしょう。 問題のテーマは、擬似言語の記述形式を細かく理解することではなく、プログラムの内容を読み取ることだからです。

このプログラムから、新たな擬似言語の分岐の構文を知ってください

code 新たな分岐の構文と意味

if
もしも
elseif
そうでなければ、もしも
else
そうでなければ
endif
if の終わり

if の後にある条件(条件はカッコで囲みます)が 真 なら、 if ブロックの処理が行われます。 ブロックとは、処理のまとまりであり、処理の先頭をインデント(スペースを何個か入れて字下げ)することで表します。

code if ブロック

「 age が 3 以下」という条件が真なら実行される

 if (age が 3 以下)
   ret ← 100

そうでない場合は、 elseif の条件が真なら、 elseif ブロックの処理が行われます。

code elseif ブロック

そうではなく空欄の条件が真なら実行される

 elseif (  )
   ret ← 300

そうでない場合は、 else ブロックの処理が行われます。

code else ブロック

そうではない場合に実行される

 else
   ret ← 500

空欄に入る条件を考えてみましょう。

この空欄の条件が 真 なら、戻り値を格納する変数 ret に 300 が代入されます。 問題に

「 4 歳から 9 歳までは 300 円」

とあるので、空欄には「 4 歳から 9 歳まで」という条件が入ります。

解答群の中で、この条件に該当するのは、選択肢カの

age が 9 以下

です。

ここでは、 4 以上という条件が不要であることに注目してください。

if ブロックの「 age が 3 以下」という条件が 真 でないときに、 elseif ブロックの条件がチェックされます。 「 age が 3 以下」という条件が 真 でないので、 age が 4 以上であることが確定しています。

そのため、 elseif ブロックの「 age が 9 以下」という条件が真なら、「 4 歳から 9 歳まで」ということになるのです。

サンプル問題(問 2 ) 新たな繰り返し構文 while と for

サンプル問題の問 2 も「プログラムの基本要素」の問題です。 出題趣旨は、

「配列の要素の並びを逆順にする処理を題材として、配列の概念を理解した上で、正しく処理を実装する能力を問う」

です。 以下に、問題を示します。

プログラムの基本要素

問 2

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

次のプログラムは,整数型の配列 array の要素の並びを逆順にする。

〔プログラム〕

整数型の配列: array ← {1, 2, 3, 4, 5}
整数型: right, left
整数型: tmp

for (left を 1 から (arrayの要素数 ÷ 2 の商) まで 1 ずつ増やす)
  right ←a
  tmp ← array[right]
  array[right] ← array[left]
  b← tmp
endfor

解答群

a b
array の要素数 – left array[left]
array の要素数 – left array[right]
array の要素数 – left + 1 array[left]
array の要素数 – left + 1 array[right]

このプログラムから、新たな擬似言語の繰り返しの構文を知ってください。

code 新たな繰り返しの構文

while および for

この問題では、 for を使っています。 for の制御記述の部分には、変数の値をどのように変化させながら繰り返すかを記述します。 ここでは、

(left を 1 から( array の要素 ÷ 2 の商)まで 1 ずつ増やす)

です。 forendfor ( for の終わりを意味します)で囲まれたブロックの中にある処理が、繰り返し実行されます。

code for ブロック

for ブロック制御記述に従ってブロックの中の処理が繰り返される

  right ←a
  tmp ← array[right]
  array[right] ← array[left]
  b← tmp

擬似言語の記述形式が変わっても、プログラムの内容を読み取るコツは同じです。それは、わかりやすい具体的なデータを想定することです。

ここでは、プログラムの中に

整数型の配列: array ← {1, 2, 3, 4, 5}

という要素数 5 個の配列 array が示されているので、この配列を想定してプログラムを読み取りましょう。 配列の要素は、 {} の中に , カンマで区切って並べます。

プログラムの内容は、配列 array の要素の並びを逆順にするのですから、 {1, 2, 3, 4, 5}{5, 4, 3, 2, 1} にします。

要素数 5 個の配列 array を想定したので、
(left を 1 から (array の要素 ÷ 2 の商) まで 1 ずつ増やす) は、 (left を 1 から 2 まで 1 ずつ増やす) になります。

問題に

「配列の要素番号は 1 から始まる」

と示されていることに注意してください。 以下は、逆順にする前と後の配列の内容です。

array[1] array[2] array[3] array[4] array[5]
1 2 3 4 5

forward 逆順にする

array[1] array[2] array[3] array[4] array[5]
5 4 3 2 1

ここで、繰り返し処理の穴埋めをするコツをお教えしましょう。 それは、最初の 1 回目の処理を想定することです。

繰り返しの処理をはじめから終わりまで、すべてトレース(処理の流れとデータの変化を追いかけること)する必要はありません。 繰り返し処理は、繰り返しのどの場面でも成り立つのですから、わかりやすい 1 回目の処理を想定して選択肢を想定するのが得策です。

最初の 1 回目の処理では、変数 left (変数の名前から配列の左側の要素番号であることがわかります)の値が 1 です。 array[1] と array[5] を交換すれば、順序が逆順になります。 そのためには、変数 right (変数の名前から配列の右側の要素番号であることがわかります)の値を 5 にする必要があります。

これが空欄 a です。

解答群の中で、 array の要素数が 5 で、 left が 1 のときに、 5 になるのは、

「 array の要素数 – left + 1 」

です。 これで、正解を選択肢ウとエに絞り込めました。

 

空欄 a の後にある処理では、変数 tmp (値を一時的に逃がすための変数なので、 temporary を意味する tmp という名前にしています)を使って、 array[left] と array[right] を交換する処理を行います。

tmp ← array[right]

で、 array[right] の値を変数 tmp に逃がしました。

array[right] ← array[left]

で、 array[right] に array[left] の値を格納しました。

あとは、変数 tmp に逃がしておいた値を array[left] に格納すればよいので

array[left] ← tmp

です。

したがって、空欄 b は array[left] であり、選択肢ウが正解です。

サンプル問題(問 3 ) 新登場 オブジェクト指向

サンプル問題の問 3 は「データ構造及びアルゴリズム」の問題です。 出題趣旨は、

「クラスを用いて各要素を表現した単方向リストを題材として、単方向リストに要素を追加する処理を実装する能力を問う」

です。以下に、問題を示します。

データ構造及びアルゴリズム

問 3

次のプログラム中のabに入れる正しい答えの組合せを,解答群の中から選べ。

手続 append は,引数で与えられた文字を単方向リストに追加する手続である。単方向リストの各要素は,クラス ListElement を用いて表現する。クラス ListElement の説明を図に示す。ListElement 型の変数はクラス ListElement のインスタンスの参照を格納するものとする。大域変数 listHead は,単方向リストの先頭の要素の参照を格納する。リストが空のときは,listHead は未定義である。

メンバ変数 説明
val 文字型 リストに格納する文字。
next ListElement リストの次の文字を保持するインスタンスの参照。初期状態は未定義である。
コンストラクタ 説明
ListElement(文字型: qVal) 引数 qVal でメンバ変数 val を初期化する。
図 クラス ListElement の説明

〔プログラム〕

大域: ListElement: listHead ← 未定義の値
○append(文字型: qVal)
 ListElement: prev, curr
 curr ← ListElement(qVal)
 if (listHead が a)
   listHead ← curr
 else
   prev ← listHead
   while (prev.next が 未定義でない)
     prev ← prev.next
   endwhile
   prev.next ← b
 endif

解答群

a b
未定義 curr
未定義 curr.next
未定義 listHead
未定義でない curr
未定義でない curr.next
未定義でない listHead

この問題では、オブジェクト指向の構文が使われています。

サンプル問題に添付された擬似言語の仕様の中には、オブジェクト指向に関して

「演算子 . は、メンバ変数又はメソッドのアクセスを表す」

という記述だけがあります。

プログラムの中では、クラスをデータ型とした変数を定義し、

変数 ← コンストラクタ(引数)

という構文で、クラスのインスタンス(メモリ上にロードされたクラスの実体であり、これをオブジェクトと呼ぶ場合もあります)を生成しています。 これらのことから、擬似言語におけるオブジェクト指向の表記は、 Java に似たものだと思われます。

 

オブジェクトは、いくつかのデータと処理をまとめたものです。 オブジェクトは、クラスとして定義され、クラスが持つデータをメンバ変数と呼び、クラスが持つ処理をメソッドと呼びます。

コンストラクタは、インスタンスの生成時に呼び出される特殊なメソッドであり、クラス名と同じ名前のメソッドにします。 多くの場合に、コンストラクタは、コンストラクタの引数で、メンバ変数の値を初期化します。

 

このプログラムで使われている ListElement クラスには、 val および next というメンバ変数と、 ListElement というコンストラクタがあります。 ListElement クラスをデータ型とした変数 curr を宣言し、

curr ← ListElement(qVal)

という処理で ListElement のインスタンスを生成し、引数 qVal を指定してコンストラクタ ListElement を呼び出しています。 引数 qVal は、メンバ変数 val に格納されます。

変数 curr には、 ListElement クラスのインスタンスの参照が格納されます。 参照とは、メモリにロードされたインスタンスがどこにあるかを示す情報(メモリアドレスのことだと考えて OK です)です。

ListElement クラスは、連結リストを実現するためのものです。 従来の擬似言語では、連結リストのつながり情報を、配列の要素番号で示していましたが、新しい擬似言語では、参照で示しています。 これは、 C 言語や Java などで連結リストを実現するときの定番の表記方法であり、 C 言語では「自己参照構造体」と呼ばれます。

連結リスト – Wikipedia

オブジェクト指向や、自己参照構造体による連結リストが取り上げられているのですから、新しい試験では、従来の試験と比べて問題自体のボリュームは小さくなっていますが、内容はかなり本格的なもの(様々なプログラミングの知識が要求されるもの)になっています。

 

それでは、問題を解いてみましょう。

大域変数(グローバル変数) listHead は、その名前が示す通り、連結リストの先頭の要素の参照を格納するためのものです。 初期状態では、未定義の値(多くのプログラミング言語では、 null で示される値)が格納されています。

大域: ListElement: listHead ← 未定義の値

手続き(関数のことです) append は、引数 qVal の値を持つ要素を連結リストに追加します。 append の最初の処理として、引数 qVal を格納した要素を新たに作成し、その参照を変数 curr に格納しています。

○append(文字型: qVal)
 ListElement: prev, curr
 curr ← ListElement(qVal)

次に、もしも listHead の値が空欄 a なら、大域変数 listHead に変数 curr を代入しています。 これは、新たに作成した要素を連結リストの先頭にしているのですから、最初の要素の場合です。 listHead の値が未定義の値なら、最初の要素なので、空欄 a は、未定義の値です。 これで、正解を解答群の選択肢ア、イ、ウに絞り込めます。

 if (listHead が a)
   listHead ← curr

空欄 b がある else ブロックは、最初の要素でない場合の処理なので、既存の連結リストの末尾の要素の次に、新たに作成した要素を追加します。 そのために、変数 prev に大域変数 listHead の値を格納し、 (prev.next が未定義でない) という条件の while ブロックで繰り返し処理を行います( while ブロックの終わりは endwhile で表します)。

 else
   prev ← listHead
   while (prev.next が 未定義でない)
     prev ← prev.next
   endwhile
   prev.next ← b

この処理では、変数 prev に prev.next を格納して、連結リストをたどっています。

これが (prev.next が未定義でない) という条件が 真 である限り繰り返されるので、繰り返しを抜けたときには、変数 prev に既存のリストの末尾の要素の参照が得られます。 その要素の次を意味するメンバ変数 prev.next に新たに作成した要素の参照を格納すれば、連結リストに要素を追加できるので、空欄 b は curr です。

code while ブロック

条件が真である限りブロックの中の処理が繰り返される

   while (prev.next が 未定義でない)
     prev ← prev.next
   endwhile

したがって、選択肢アが正解です。

サンプル問題の正解

問 1 - カ 問 2 - ウ 問 3 - ア

以上、「基本情報技術者試験 科目 B 試験のサンプル問題」の中から、アルゴリズムとプログラミングの問題を取り上げ、従来からの変更点を説明しました。 2023 年 4 月以降に基本情報技術者試験を受験される方の参考になれば幸いです。

なお、アルゴリズムとプログラミングのサンプル問題は、全部で 5 問が公開されています。 今回は、それらの中から 3 問を取り上げました。残りの 2 問は、今後の記事で取り上げる予定です。

label 関連タグ
科目A試験は、
免除できます。
独習ゼミで科目A試験を1年間免除して、科目B試験だけに集中しましょう。
免除試験を受けた 74.9% の方が、
科目A免除資格を得ています。
科目A免除試験 最大 2 回の
受験チャンス !
info_outline
科目A免除試験 最大 2 回の
受験チャンス !
詳しく見てみるplay_circle_filled
label これまでの『資格ガイド』の連載一覧 label 著者