戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

基本情報技術者 2013年 春期 午後 問11


次のJavaプログラムの説明及びプログラムを読んで、設問1〜3に答えよ。

〔プログラムの説明〕  あみだくじの作成と結果の表示を行うプログラムである。  あみだくじとは、複数の平行に並ぶ縦線と、2本の縦線だけに水平に接続する複数の横線から成るくじである。横線は縦線の上端及び下端には接続せず、縦線の同一箇所に複数の横線が接続されることもない。くじをたどる手順は次のとおりである。 (1) 1本の縦線を選択し、上端から下方向にたどり始める。 (2) 途中に、接続する横線があるときは必ず曲がり、もう一方の縦線までたどる。 (3) 縦線に到達したら、また下方向にたどる。 (4) 下端に到達するまで(2)と(3)を繰り返す。 (5) 下端に到達したときの縦線の位置が、くじを引いた結果である。  あみだくじの例を図1に示す。図中の太線は、左端の縦線を選択したときにたどった経路である。
基本情報技術者試験(平成25年 午後 問11 図1)
 クラスGhostLegは、あみだくじを作成し、作成したあみだくじをたどるプログラムである。 (1) 縦線を左からの順番で保持する。左端を0番目とする。 (2) 縦線の長さを1.0とし、上端の縦軸座標を1.0、下端の縦軸座標を0.0とする。 (3) 横線の両端の縦軸座標は等しく、0.0よりも大きく1.0未満である。 (4) 縦線の本数を引数とするコンストラクタをもつ。 (5) 次のメソッドをもつ。  ① void addHorizontalLine(int x1, int x2, double y)   横線を追加するメソッドである。左からx1番目の縦線とx2番目の縦線を縦軸座標yで接続する横線を追加する。ただし、x1とx2が等しいか、2本の縦線のいずれか又は両方に、既に縦軸座標yで接続する横線があるときには追加しない。   あみだくじは、クラスGhostLegのインスタンスを生成した後、このメソッドを任意の回数だけ呼び出し、横線を追加することによって完成する。  ② int trace(int x)   くじを引いた結果を返すメソッドである。左からx番目の縦線を選択し、あみだくじをたどった結果を返す。    クラスGhostLegTesterはテスト用のプログラムである。このプログラムは、図1に示したあみだくじを作り、左から順にくじを引き、結果を表示する。実行結果を、図2に示す。
基本情報技術者試験(平成25年 午後 問11 図2)
基本情報技術者試験(平成25年 午後 問11 プログラム1)
基本情報技術者試験(平成25年 午後 問11 プログラム2)

設問1:

問題文を見る
 次の記述中のに入れる正しい答えを、解答群の中から選べ。    クラスGhostLegの内部クラスVerticalLineは1本の縦線を表すクラスであり、インスタンスは、そのインスタンスが示す縦線に接続している横線を保持している。この内部クラスでは、横線を、として表現している。   解答群  ア:クラスHorizontalLineのインスタンスの列  イ:その横線が接続する縦軸座標とクラスHorizontalLineのインスタンスのマップ  ウ:その横線が接続する縦軸座標とその横線に接続するもう1本の縦線のマップ  エ:その横線に接続する2本の縦線のマップ

模範解答

ウ

解説

解答の導き方

この設問では、内部クラスVerticalLineが横線をどのようなデータで表しているかを、プログラムから読み取ります。
まず、VerticalLineの中には、horizontalLinesというSortedMapがあります。マップとは、キーと値を組にして保存するデータ構造です。SortedMapは、キーの順に並べてデータを保持します。
宣言では、キーの型がDouble、値の型がVerticalLineです。つまり、横線が接続している縦軸座標をキーにし、その横線でつながるもう一方の縦線を値にしていると分かります。
このことは、横線を追加する処理からも確認できます。putHorizontalLine(y, opposite)は、縦軸座標yをキーにして、接続先の縦線を値として保存します。また、横線の両端にある縦線それぞれに、相手側の縦線を保存しています。そのため、どちらの縦線からたどり始めても、横線の接続先を調べられます。
実際にtraceでは、まず現在の縦線について、現在の座標より下にある横線の座標をgetNextYで求めます。次に、その座標を使ってgetOppositeから接続先の縦線を取り出します。座標と接続先の縦線を組にして保存しているため、この処理ができます。
なお、コンストラクタでは座標0.0にnullを登録しています。これは実際の横線ではなく、横線の座標を探すときに下端の目印として使われます。横線の情報そのものは、「縦軸座標」と「接続先の縦線」の組です。
したがって、「その横線が接続する縦軸座標」と「その横線に接続するもう1本の縦線」を対応付けたウが、プログラムの表現と一致します。

誤りやすいポイント

  • マップのキーと値の役割を逆にしないようにします。このプログラムでは、キーが縦軸座標、値が接続先の縦線です。
  • 選択肢イは、値がクラスHorizontalLineのインスタンスです。しかし、プログラムでは横線を表すインスタンスではなく、接続先のVerticalLineを値として使っています。
  • 選択肢エは、2本の縦線をマップにする表現です。しかし、このマップのキーは縦線ではなく、縦軸座標です。
  • 0.0にnullが登録されていることだけを見て、横線を「座標と横線のインスタンス」で管理していると考えないようにします。0.0は下端の目印です。

FAQ

Q: なぜ横線の両端にある縦線の両方に、接続先を保存するのですか?
A: どちらの縦線を選んでも、横線をたどったときに相手側の縦線を調べられるようにするためです。
Q: SortedMapを使うと、どのような処理ができますか?
A: キーが順に並ぶため、現在の座標より小さいキーの中から、最も大きいものを見つけられます。これは、上から下へたどるときに、次の横線の座標を探す処理に使われています。
Q: 0.0に保存されているnullは何を表しますか?
A: 横線の接続先ではなく、下端の目印です。横線の座標を探すときに、下端までたどったことを判断するために使われます。

関連キーワード: マップ、キーと値、ソート、データ構造、内部クラス

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 プログラム中のに入れる正しい答えを、解答群の中から選べ。   aに関する解答群  ア:ghostLeg  イ:GhostLeg  ウ:void ghostLeg  エ:void GhostLeg   bに関する解答群  ア:0  イ:i  ウ:new VerticalLine()  エ:null   cに関する解答群  ア:-1.0  イ:0.0  ウ:x  エ:y   dに関する解答群  ア:horizontalLines.get(x)  イ:horizontalLines.get(y)  ウ:v.getOpposite(y)  エ:verticalLines.get(x)

模範解答

a:イ、b:ウ、c:イ、d:ウ

解説

解答の導き方

空欄a〜dは、クラスの作り方と、あみだくじを下へたどる処理を順に確認すると判断できます。
a:コンストラクタの名前
コンストラクタは、インスタンス(クラスをもとに作った実物)を作るときに初期化を行う特別な処理です。名前はクラス名と同じになります。
このクラスの名前はGhostLegなので、コンストラクタはpublic GhostLeg(int n) です。また、コンストラクタには戻り値の型を書きません。したがって、aは「イ:GhostLeg」です。「void ghostLeg」や「void GhostLeg」のようにvoidを付けたものは当てはまりません。
b:縦線を表すインスタンス
コンストラクタでは、引数nで指定された本数だけ繰り返し、縦線をリストに追加しています。リストは、要素を順番に保持する入れ物です。
リストに追加するのは、縦線の情報を持つVerticalLineのインスタンスです。そのため、繰り返しのたびにnew VerticalLine() として新しいインスタンスを作ります。整数やnullでは、縦線ごとの情報を持たせられません。よって、bは「ウ:new VerticalLine()」です。
c:下端に到達したかどうか
問題文では、縦線の上端の座標は1.0、下端の座標は0.0とされています。また、getNextY(y) は、現在の座標yより小さい横線の座標を返します。
この処理では、getNextY(y) で次の座標に更新した後、その値が0.0より大きい間、横線をたどります。座標が0.0になったら下端に到達したので、ループを終えます。したがって、cは「イ:0.0」です。
d:横線の接続先への移動
getNextY(y) が返した値は、現在の縦線で次にたどる横線の座標です。その横線の反対側にある縦線へ移るには、現在の縦線vから、その座標の接続先を取得します。
VerticalLineの中では、横線の座標をキー、接続先の縦線を値としてhorizontalLinesに記録しています。getOpposite(y) は、その座標yに接続している相手の縦線を返すメソッドです。よって、dは「ウ:v.getOpposite(y)」です。
左から0番目の縦線を選ぶ場合、たどる順序は次のようになります。
現在の縦線次の横線の座標横線を渡った後の縦線
00.81
10.42
20.23
30.0下端に到達
getNextY(y) は、現在の座標より小さい横線のうち、最も大きい座標を返します。各縦線には下端を表す0.0も登録されているため、次の横線がなくなると0.0が返り、たどる処理が終わります。この例では、最初に縦線0を選ぶと、最終的に縦線3に到達します。

誤りやすいポイント

  • コンストラクタには戻り値の型を書きません。メソッドと同じようにvoidを付けると誤りです。
  • リストの初期容量を指定することと、リストに要素を追加することは別の処理です。縦線を追加するには、new VerticalLine() で縦線のインスタンスを作ります。
  • ループの条件で確認するのは、更新前のyではなく、getNextY(y) を実行した後のyです。更新後の値が0.0なら、下端に到達したことになります。
  • 横線の接続先は、現在の縦線vから取得します。getOpposite(y) に渡すyは、次にたどる横線の座標です。

FAQ

Q:各縦線に0.0を登録しておくのはなぜですか?
A:現在の位置より下に横線がなくなったとき、getNextY(y) が下端の座標0.0を返せるようにするためです。これによって、下端に到達したことを判定できます。
Q:getNextY(y) は、なぜyより小さい座標を探すのですか?
A:くじは上端から下方向へたどるためです。現在の位置より下にある横線のうち、次に通る横線を探しています。
Q:getOpposite(y) は何を返しますか?
A:現在の縦線に、座標yで接続している横線の反対側にある縦線を返します。

関連キーワード: コンストラクタ、インスタンス、リスト、マップ、ループ

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 次の記述中のに入れる正しい答えを、解答群の中から選べ。    メソッドaddHorizontalLineの呼出しにおいて、引数x1又はx2に相当する縦線がないときにはIndexOutOfBoundsExceptionが投げられる。一方、引数yには追加する横線の縦軸座標を指定するので、その値は0.0よりも大きく1.0未満でなければならないが、それ以外の値を指定しても例外は投げない。  これを、引数x1及びx2の値によらず、引数yの値が横線の縦軸座標として取り得る範囲から外れているときにIllegalArgumentExceptionを投げるようにするには、プログラム1中のコメント“// 設問3(e)”の1行を次のif文に置き換えればよい。    if (f) {   throw new IllegalArgumentException();  }   eに関する解答群  ア:α  イ:β  ウ:γ  エ:δ   fに関する解答群  ア:y <= 0.0 && y >= 1.0  イ:y <= 0.0 || y >= 1.0  ウ:y > 0.0 && y < 1.0  エ:y > 0.0 || y < 1.0

模範解答

e:ア、f:イ

解説

解答の導き方

この設問では、引数 が横線の縦軸座標として正しい範囲にあるかを調べる処理を、どこに置き、どの条件で例外を投げるかを考えます。
  1. に認められる範囲を確認します。
    問題文では、横線の縦軸座標は「0.0よりも大きく1.0未満」とされています。つまり、 と は範囲に含まれません。範囲内である条件は次のとおりです。
    y > 0.0 && y < 1.0
    
    && は「かつ」です。 は、 より大きく、同時に より小さくなければなりません。
  2. 範囲外を表す条件を考えます。
    範囲外なのは、 が 以下の場合、または 以上の場合です。どちらか一方に当てはまれば範囲外なので、条件は次のとおりです。
    y <= 0.0 || y >= 1.0
    
    || は「または」です。範囲外になる場合を分けると、次のようになります。
    • なら、下限を満たしません。
    • なら、上限を満たしません。
    このどちらかに当てはまる場合に、IllegalArgumentExceptionを投げます。これは、引数の値が不適切であることを示す例外です。
  3. 範囲を調べる処理を置く位置を考えます。
    addHorizontalLineでは、x1番目、x2番目の縦線を順に取り出します。指定された位置に縦線がない場合は、IndexOutOfBoundsExceptionが投げられます。これは、指定した番号の要素がないことを示す例外です。
    設問では、x1やx2の値によらず、 が範囲外なら IllegalArgumentException を投げるようにします。そのためには、縦線を取り出す前に の範囲を確認する必要があります。
    たとえば、 が範囲外で、x1番目の縦線も存在しない場合を考えます。範囲確認が縦線を取り出した後にあると、先に IndexOutOfBoundsException が投げられ、 の範囲を確認できません。範囲確認を最初に行う位置は「// 設問3(α)」です。
    したがって、eにはα、fには範囲外の条件である「 または 」を選びます。

誤りやすいポイント

  • 範囲内の条件と範囲外の条件を取り違えないようにします。 かつ は範囲内の条件です。例外を投げる条件には、 または を使います。
  • 範囲外の条件を「かつ」で結ばないようにします。 が 以下の場合と、 以上の場合のどちらかに当てはまれば範囲外なので、「または」で結びます。
  • 範囲確認を縦線の取り出しより後に置かないようにします。x1やx2が不正な場合、先に別の例外が投げられてしまうためです。

FAQ

Q: がちょうど0.0または1.0のときは、範囲内ですか?
A: どちらも範囲外です。「0.0よりも大きく1.0未満」なので、0.0と1.0は含まれません。
Q: x1やx2が不正な場合でも、必ず IllegalArgumentException が投げられますか?
A: も範囲外なら、先に範囲を確認するため IllegalArgumentException が投げられます。 が範囲内なら、その後に縦線を取り出す処理で、番号が不正な場合に IndexOutOfBoundsException が投げられます。
Q: 範囲外の条件に「または」を使うのはなぜですか?
A: 範囲外になるのは、下限より低い場合か、上限以上の場合のどちらかです。両方を同時に満たす必要はないため、「または」を使います。

関連キーワード: Java例外処理、条件式、論理演算子、境界値、引数検査

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

基本情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について