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

応用情報技術者 2016年 春期 午後03


ライフゲームに関する次の記述を読んで、設問1〜5に答えよ。

 ライフゲームとは、数学者コンウェイが考案した、生命の誕生、生存、死滅などを再現したシミュレーションゲームである。マス目状の盤上の各マスに生命が存在でき、そのマス自身及び隣接するマスの状態によって次世代の誕生、生存、死滅が決まる。その条件を表1に示す。  なお、隣接するマスには、斜め方向のマスも含む。また、生命が存在するマスを“生のマス”、生命が存在しないマスを“死のマス”と呼ぶ。
応用情報技術者試験(平成28年度 午後 問03 表01)
〔4×4マスのシミュレーション〕  4×4マスの盤上における第3世代までのシミュレーションを図1に示す。
応用情報技術者試験(平成28年度 午後 問03 図01)
 第1世代は、初期値として設定されたものである。例として、第1世代の2行目1列目のマスを考える。現在、このマスは死のマスである。このマスに隣接するマスを網掛けで示す。これら五つのマスの中に生のマスが三つある。これは表1の“誕生”の条件に該当するので、第2世代の2行目1列目のマスは生のマスになる。同様に、第1世代の各マスについて、そのマス自身及び隣接するマスの状態を確認することで第2世代が決まる。次の世代への状態の更新は、全てのマスについて同時に行われる。   〔盤上のマスのデータ構造〕  N×Nマスの盤上の状態を表すデータ構造を考える。多次元配列が利用できないプログラム言語を考慮し、盤上の各マスの生死状態を管理するデータ構造として1次元配列 m を用いる。配列 m のデータ構造のイメージを図2に示す。
応用情報技術者試験(平成28年度 午後 問03 図02)
〔配列 m を次世代に更新するプログラム〕  使用する定数、配列及び関数を表2に、配列 m を次世代に更新する関数 update を図3に示す。  なお、関数に配列を引数として渡すときの方式は参照渡しである。
応用情報技術者試験(平成28年度 午後 問03 表02)
応用情報技術者試験(平成28年度 午後 問03 図03)
〔テストプログラム〕  図3のプログラムをテストするために、配列 m に第1世代が与えられたときの第 p 世代が、机上で作成した正しい結果である配列 r と等しいことを確認するプログラムを作成した。作成した関数 shouldBe を図4に示す。ここで、p には 2 以上の整数が入る。
応用情報技術者試験(平成28年度 午後 問03 図04)
 図3のプログラムが正しく動作する状態で図4のプログラムを実行したところ、テストが失敗した。原因を調査した結果、図4の行目に問題があることが判明したので、①プログラムを修正してテストを成功させることができた。

設問1

図1中のに入れる適切な生成状態を、図1の凡例に従い答えよ。

模範解答

ア:× イ:× ウ:○ エ:○

解説

解答の論理構成

  1. 第2世代の盤面は【問題文 図1】で与えられています。対象となる 4 マスは
    :2 行 2 列
    :3 行 2 列
    :3 行 3 列
    :4 行 2 列
    です。
  2. 各マスに隣接する“生”マスの個数を数えます(上下左右斜めの 8 方向。盤端は盤外を数えません)。
    • 周囲の“生”マス=4 個
    • 周囲の“生”マス=4 個
    • 周囲の“生”マス=3 個
    • 周囲の“生”マス=3 個
  3. 【問題文 表1】の規則を適用します。引用中の数字・語句は原文そのままです。
    • 誕生規則 「死のマスに隣接する生のマスが三つならば、死のマスは次の世代では生のマスとなる。」
    • 生存規則 「生のマスに隣接する生のマスが二つ又は三つならば、生のマスは次の世代でも生のマスである。」
    • 過密規則 「生のマスに隣接する生のマスが四つ以上ならば、生のマスは過密によって次の世代では死のマスとなる。」
    • 過疎規則は今回は該当なし(“一つ以下”のマスはない)
  4. 判定結果
    • は“死”で 4 個 → 誕生条件を満たさず“死”のまま(×)。
    • は“生”で 4 個 → 過密で“死”になる(×)。
    • は“生”で 3 個 → 生存し続ける(○)。
    • は“死”で 3 個 → 誕生して“生”になる(○)。
以上より
ア:× イ:× ウ:○ エ:○

誤りやすいポイント

  • 盤端のマスは盤外を含めて 8 個そろわないため、実際に存在するマスだけを数えます。盤外を“死”として数えてしまうと誤判定になります。
  • “誕生”と“生存”を混同しやすいです。誕生は“死”マス限定、かつ隣接“生”マスが「三つ」のみ。
  • “生”マスの「三つ」は生存でも条件に含まれるため、現在の状態(生/死)を先に確認しないと判定を取り違えます。

FAQ

Q: 同時更新とは何を意味しますか?
A: 【問題文】にある「次の世代への状態の更新は、全てのマスについて同時に行われる。」のとおり、ある世代 n の判定には世代 n の状態だけを用い、途中で変化した結果を使ってはいけません。
Q: “過疎”と“過密”のどちらを優先しますか?
A: 優先順位はなく、条件を満たすかどうかで決まります。生マスで 4 個以上なら即“過密”、1 個以下なら即“過疎”です。
Q: 4×4 以外のサイズでも規則は同じですか?
A: はい。【問題文 表1】の規則は N×N どのサイズでも共通に適用されます。

関連キーワード: セルオートマトン, 同時更新, 近傍数, 過密死, 誕生条件

設問2

図2中のに入れる適切な符号を答えよ。

模範解答

オ:(k−1)×N+j

解説

解答の論理構成

  1. 【問題文】の図2には「行1・列1 m[1]」「行1・列2 m[2]」「行1・列N m[N]」「行2・列1 m[N+1]」「行2・列N m[2×N]」と具体例が列挙されています。
  2. これらを行番号 、列番号 で一般化すると、配列 m の添字は
     ・行が 1 増えるごとに ずつ増加
     ・同じ行内では列番号に一致
     という規則で並んでいると分かります。
  3. したがって基準位置(行1)の先頭 m[1] から 行下へ移動すると 回加算し、列位置は を足す形になります。
  4. 以上より「行k・列j」の要素は
     
    と表されます。これが図2の に入る符号です。

誤りやすいポイント

  • 0 始まりと 1 始まりの添字を混同し、(k×N)+j や (k-1)×N+(j-1) とずらしてしまう。
  • 行を先に掛けるとき括弧を忘れ、k-1×N と計算順序を誤る。
  • 行・列を逆に解釈して j×N+(k-1) としてしまう。

FAQ

Q: 行列を一次元配列に写像するときは常に になりますか?
A: 配列を 1 始まりで管理し、行を上から、列を左から増やす一般的な「行優先 (row-major)」配置ならば成立します。0 始まりや列優先配置では式が変わります。
Q: (k−1)×N+j と N×(k−1)+j は同じですか?
A: 乗算は可換なので結果は同じですが、試験解答では【問題文】の記述に合わせて と書くのが安全です。
Q: 行数や列数が可変でも式は変わりませんか?
A: はい。盤の一辺の大きさを表す定数 N をそのまま用いれば盤の拡大・縮小に関係なく同じ式で添字を計算できます。

関連キーワード: 配列添字, 行優先配置, 一次元配列化, オフバイワン, インデックス計算

設問3

図3中のに入れる適切な字句を答えよ。

模範解答

カ:temp[c]と1が等しい キ:(temp[i]と0が等しい)and(eと3が等しい) ク:m[i] ← 1

解説

解答の論理構成

  1. 周囲の生きているマス数を数える部分
    • 図3では隣接 8 マスを走査し、生きている場合に e ← e + 1 で加算します。
    • “生きている”かどうかの判断は、更新前状態を退避した temp を参照すべきであり、式は
      temp[c]と1が等しい
      となります。これが[カ]です。
  2. 誕生判定(死→生)
    • 表1の“誕生”条件は「死のマスに隣接する生のマスが三つならば、死のマスは次の世代では生のマスとなる。」
    • i 番目のマスが死(temp[i]と0が等しい)かつ生きている隣接マス数 e が 3 のとき生にするので
      (temp[i]と0が等しい)and(eと3が等しい)
      が[キ]になります。
  3. 生存判定(生→生)
    • 表1の“生存”条件は「生のマスに隣接する生のマスが二つ又は三つならば、生のマスは次の世代でも生のマスである。」
    • 既に生(temp[i]と1が等しい)の場合は if-elseif の elseif 節で処理され、条件式はコード内で既に与えられています。
    • 条件を満たしたとき、新世代配列 m に生を設定する文が必要であり、字句は
      m[i] ← 1
      となります。これが[ク]です。
  4. 以上より
    • [カ] temp[c]と1が等しい
    • [キ] (temp[i]と0が等しい)and(eと3が等しい)
    • [ク] m[i] ← 1
      が模範解答と一致します。

誤りやすいポイント

  • 退避配列 temp を使わずに m を参照してしまう
    (同時更新を壊し、世代計算が逐次更新になってしまう)。
  • “誕生”と“生存”の条件を混同し、e=3 なのに元が生のマスだけを対象にしてしまう。
  • “生存”条件で e=2 or 3 の判定は正しくても、新世代配列 m に値を代入し忘れる。

FAQ

Q: 退避用配列 temp は必ずコピーでなくスワップでも良いですか?
A: はい。性能を優先する実装ではポインタを入れ替えても構いませんが、本問は“参照渡し”前提でコピーを採用しています。
Q: 盤面端のマスで配列外アクセスが起きませんか?
A: c が 1 以上 かつ c が N×N 以下 のチェックを行っているため安全です。
Q: “過疎”と“過密”を個別にコード化しない理由は?
A: 生存条件(e=2 or 3)を満たさない生マスは自動的に死へ更新されるので、過疎・過密を区別して書く必要がありません。

関連キーワード: 隣接マス探索, 一次元配列インデックス変換, 同時更新, セルオートマトン, 条件分岐

設問4

図3中のαの二つの条件のいずれかを満たすのはどのような場合か。単語“盤”及び“マス”を用いて30字以内で述べよ。

模範解答

チェックするマスが盤の第1列又は第N列の場合

解説

解答の論理構成

  1. ライフゲームの隣接判定では、対象マスが盤の端にある場合は左右方向に存在しないマスが出るので、走査範囲を制限する必要があります。
  2. 図3の α 部分では、端判定のために次の 2 行が使われています。
    • if( i-1 が N で割り切れる )
    • elseif( i が N で割り切れる )
  3. 1 行目は「i-1 が N で割り切れる」――すなわち i が 1, N+1, 2N+1 … という配列先頭列に対応するインデックスである場合です。これは「盤の第1列」に相当します。
  4. 2 行目は「i が N で割り切れる」――すなわち i が N, 2N, 3N … という末尾列に対応するインデックスである場合で、「盤の第N列」を表します。
  5. いずれかに該当すれば左右どちらかが盤外になるため、図3では a と b (横方向の探索開始・終了)の値を調整し、配列境界を越えないようにしています。
  6. したがって α の 2 条件をまとめると「チェック対象が盤の左右端のマスである場合」となり、模範解答「チェックするマスが盤の第1列又は第N列の場合」が導かれます。

誤りやすいポイント

  • i-1 と i のどちらで割り切り判定しているかを取り違え、左端と右端を逆に解釈してしまう。
  • 行端だけでなく行頭・行末の「列」端を問う設問であることを見落とし、「第1行・第N行」と答えてしまう。
  • 1 次元配列の線形番号をそのまま行番号と誤読し、N で割り切れる条件を「最下行」と解釈してしまう。

FAQ

Q: i-1 が N で割り切れる が第1列になる理由は?
A: 配列は 1 始まりです。列 1 のインデックスは 1, N+1, 2N+1 … であり、それぞれ i-1 が 0, N, 2N … と N の倍数になります。
Q: 行端(上端・下端)の処理はどこで行っていますか?
A: 上下方向は for( y を ‑1 から 1 まで … ) 内で c ← i + y × N + x を計算した後、( c が 1 以上 ) and ( c が N×N 以下 ) という範囲チェックで盤外かを判定しています。
Q: 仮に盤外をチェックしなかったらどうなりますか?
A: 線形インデックスが 0 や N×N+1 など実配列外を指し、実行時エラーや誤った隣接数カウントを招きます。

関連キーワード: 一次元配列, 端判定, 余り演算, 隣接探索, ライフゲーム

設問5〔テストプログラム〕について、(1)、(2)に答えよ。

(1)本文中のに入れる適切な数値を答えよ。

模範解答

ケ:2

解説

解答の論理構成

  1. 【問題文】には
      “図4の行目に問題があることが判明したので、①プログラムを修正してテストを成功させることができた。”
     とあります。つまり、shouldBe 内の「どの行」が誤りの原因かを特定する設問です。
  2. 図4を確認すると、次の二つの for 文が同じループ変数 i を使っています。
       2: for( i を1からpまで1ずつ増やす )  5: for( i を1からN×Nまで1ずつ増やす )  
  3. 2 行目のループが終了した時点で i には p+1 が入っています。続く 5 行目のループ開始条件
     for( i を1からN×Nまで1ずつ増やす )
     は、ループ変数 i を再初期化するはずですが、多くの言語では 5 行目の for 文が始まるときに i を 1 に戻しません。結果、5 行目のループが1回も回らず、配列 m と r の比較が行われなくなります。
  4. このバグを防ぐもっとも単純な修正は、2 行目のループ変数名を i 以外に変更することです。したがって“問題のある行”は 2 行目であると論理的に確定できます。
  5. 以上より、 に入る適切な数値は 2 です。

誤りやすいポイント

  • 同一関数内でループ変数を使い回し、後続のループがスキップされるバグに気づけない。
  • “行番号”を問われているのに、“修正内容”を答えようとしてしまう。
  • 図4のコメント行(// テスト失敗 など)を行番号に含めて数え、番号をずらしてしまう。

FAQ

Q: なぜ 5 行目では自動的に i が 1 に戻らないのですか?
A: 多くの言語では for 文の初期化部はループの“開始時”に評価されます。2 行目のループが終わっても i はスコープ内で存続し、5 行目の for 文が実行される時点で i の値は p+1 のままです。
Q: 変数名を変える以外の対策はありますか?
A: 例えば 2 行目と 5 行目の for 文を入れ子にせず、テスト用配列を別関数で比較する方法がありますが、最小修正は変数名の変更です。
Q: update(m) を呼び出す回数自体に誤りはありませんか?
A: 【問題文】で“p には 2 以上の整数が入る”とされており、2 行目のループで update(m) を p 回呼び出す仕様は正しいです。

関連キーワード: ループ変数, スコープ, 配列比較, バグ修正

設問5〔テストプログラム〕について、(1)、(2)に答えよ。

(2)本文中の下線①の修正後の行目のプログラムを答えよ。

模範解答

for(iを2からpまで1ずつ増やす)

解説

解答の論理構成

  1. 初期値として与えられている配列 m は “第1世代” である
    ― 【問題文】「第1世代は、初期値として設定されたものである。」
  2. 関数 update は 1 回呼び出すごとに “次の世代” を作る
    ― 【問題文】「次の世代への状態の更新は、全てのマスについて同時に行われる。」
  3. p 世代を得るには、第1世代から (p-1) 回の update が必要
    ― 例えば p=2 なら update を 1 回、p=3 なら 2 回で第3世代になる。
  4. 図4の元の 行は
    「2: for( i を1からpまで1ずつ増やす )」
    これでは update が p 回実行され、第(p+1)世代になってしまう。
  5. 最初の 1 回目を飛ばし、i=2 から p まで回せば update の総回数は (p-1) 回になる。
    よって修正後の 行は
    「for(iを2からpまで1ずつ増やす)」

誤りやすいポイント

  • 「第1世代=0 回更新」と数え間違え、p 回 update してしまう。
  • update に副作用があるため、ループ条件を誤ると一気に全要素がずれる。
  • p=2 の最小ケースでテストせず、バグを見逃しやすい。

FAQ

Q: p=1 のときはどうしますか?
A: 問題文に「p には 2 以上の整数が入る」とあるので想定外です。特別な処理は不要です。
Q: ループ変数を 0-based にしても良いですか?
A: 可能ですが、その場合は開始値と比較値の両方を 0-based に合わせ、(p-1) 回の実行になるよう調整してください。
Q: update の戻り値を使う方法ではダメですか?
A: 今回の仕様では update は副作用型(参照渡し)で設計されています。戻り値に変えるとテスト関数側を全面的に書き換える必要があり、本設問の趣旨から外れます。

関連キーワード: ライフゲーム, 世代カウント, テストループ, オフバイワンエラー
戦国ITクイズ機能

\ せっかくなら /

応用情報技術者
クイズ形式で学習しませんか?

クイズ画面へ遷移する

すぐに利用可能!

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

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