基本情報科目B-サンプル問題【全44問をがっつり解説】

※一部、執筆途中です。随時アップしていきます。
※サンプル問題だけを解くのは,非効率です。詳細は以下の動画をご確認ください。

令和4年度4月)

✓R404-問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 より小さい

解説を開く

正解はカ age が 9 以下 です。

①【】内の分岐がTrueの時に実行される処理はret ←300(入場料を300円に設定する処理)です。

②問題文より入場料が300円になるのは、「4歳から9歳まで」。

③最初のifでageが3以下を判定済みなので、if(【  】)に到達する時点で3以下には当てはまらない、つまり4以上であることがわかります。

④あとは「9歳まで」かどうかを判定すればいいので、正解はカage が 9 以下(カ)です。

(他の選択肢)
ア (age が 4 以上) and (age が 9 より小さい) は「9より小さい」に9歳が含まれないため×
ウ (age が 4 より大きい) and (age が 9 以下) は「4より大きい」に4歳が含まれないため×

選択肢にはないですが`(ageが4以上) and (ageが9以下)`も、正解になりえます。
`(ageが4以上)`はプログラム的には余計な記述ですが、人間が理解しやすいため、現場では`(ageが4以上) and (ageが9以下)`と書くほうが一般的です。
※現場にもよります。ナノ秒単位の処理速度が求められる場合、余計な記述は避け、`age が 9 以下`とすべきです。

✓R404-問2(配列&繰り返し)

次のプログラム中の【 a 】と【 b 】に入れる正しい答えの組合せを、解答群の中から選べ。ここで、配列の要素番号は 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]
解説を開く

正解はウです。

まず、次のプログラムは、整数型の配列 array の要素の並びを逆順にする。とあるため、最終的にはarrayの配列以下となるはずです。

array

1 2 3 4 5
5 4 3 2 1

さらに選択肢から以下のことがわかります。

  • 【a】はarrayの要素数-leftarrayの要素数-left+1のどちらか
  • 【b】はarray[right]array[left]のどちらか

【 b 】 ← tmp

解答群がシンプルな、【b】から先に考えます。

候補はarray[right]array[left]のどちらかであり、【b】の前後の処理は以下です。

  tmp ← array[right]
  array[right] ← array[left]
  【 b 】 ← tmp

array[right]を入れた場合、array[right]←が2行続くことになり、array[right] ← array[left](を含む、上記3行すべて)が意味のない処理になります。
array[left]であれば、意味の無い処理にはなりません。よって、【b】はarray[left]です。

right ← 【 a 】

候補はarrayの要素数-leftarrayの要素数-left+1のどちらかです。
1周目の時leftは1なので、arrayの要素数-leftは4、arrayの要素数-left+1は5です。

このあとの処理を見ると、array[right] ← array[left]によって、要素番号rightの位置に1が代入されます。
完成形より、1はarray[5]に入るべきなので、【a】はarrayの要素数-left+1です。

よって、正解はウです。

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

Memo:(別解)トレースした場合

  • 【a】はarrayの要素数-leftarrayの要素数-left+1のどちらか
  • 【b】はarray[right]array[left]のどちらか

上記を踏まえ【a】までの処理をトレースします。

array

1 2 3 4 5
1 2 3 4 5
left(1~2) right tmp
1

right ← 【 a 】

arrayの要素数-leftは4、arrayの要素数-left+1は5です。

left(1~2) right tmp
1 4 or 5

tmp ← array[right]
array[right] ← array[left]

left(1~2) right tmp array[right] ← array[left]
1 4 or 5 array[4 or 5] array[4 or 5] ← array[1]
      1

ここでarray[right] ← array[left]に注目します。
`array[right] ← array[1]です。

完成形を考慮すると、1はarray[5]に入るべきです。

array

1 2 3 4 5
5 4 3 2 1

よって【a】は、leftが1のときに5となるarrayの要素数-left+1です。

【 b 】 ← tmp

候補は、array[right]array[left]のどちらかです。
tmpには5が入っています。

left(1~2) right tmp array[right] ← array[left]
1 4 or 5 array[4 or 5]
5
array[4 or 5] ← array[1]
      1

array

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

5はarray[1]に入るべきです。よって【b】は、array[left]`です。

よって、正解はウです。

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

Point:変数同士の値の入れ替え

変数同士の値の入れ替えは、以下の形が一般的です。

tmp ← ★
★ ← ☆
☆ ← tmp

上記を知っていれば、【b】はarray[left]だとすぐに解答できます。

tmp ← array[right]
array[right] ← array[left]
【 b 】 ← tmp

array[right] ← tempだと、その前の処理array[right] ← array[left]が意味の無い処理になります。このことからも、leftが答えだと推測できます。

Point:配列を右から取得するn-i+1

配列の要素数-i+1は、配列の右からi番目の要素を指します。(今回の場合、1周目に5,2周目に4と変化します。)
leftがi(繰り返し回数)の役割を果たしているとわかれば、【a】は配列の要素数-left+1だとわかります。

✓R404-問3 リスト

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

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

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

コンストラクタ 説明
ListElement(文字型:qVal) 引数 qVal でメンバ変数 val を初期化する。

〔プログラム〕

大域: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
解説を開く

成果はアです。

①【a】
curr ← ListElement(qVal)より、
仮にDを引数とした場合、currentは以下の状態です。

val “D”
next 未定義
  if(listHead が 【 a 】)
    listHead ← curr

listHeadにcurrへの参照を代入するのは、listHeadが空、つまり未定義のとき(リストが空のときは,listHead は未定義である。より)です。

②【b】

listHeadが空でない場合、リストは以下のような状態です。

(参照順に振った番号) 1(listHead) 2 3
val “A” “B” “C”
next Bへの参照 Cへの参照 未定義

ここに”D”を追加して、以下のような状態としたいです。

(参照順に振った番号) 1(listHead) 2 3 4
val “A” “B” “C” “D”
next Bへの参照 Cへの参照 Dへの参照 未定義
    prev ← listHead
    while(prev.next が 未定義でない)
      prev ← prev.next
    endwhile
    prev.next ← 【 b 】

prevにはlistHeadへの参照を代入した上で、prev.next が 未定義になるまで繰り返すと、Cへの参照がprevに代入されます。

✓R404-問4(2次元配列)

次の記述中の【 a 】〜【 c 】に入れる正しい答えの組合せを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる。

要素の多くが 0 の行列を疎行列という。次のプログラムは,二次元配列に格納された行列のデータ量を削減するために,疎行列の格納に適したデータ構造に変換する。

関数 transformSparseMatrix は,引数 matrix で二次元配列として与えられた行列を,整数型配列の配列に変換して返す。
関数 transformSparseMatrix を
transformSparseMatrix({{3,0,0,0,0},{0,2,2,0,0},{0,0,0,1,3},{0,0,0,2,0},{0,0,0,0,1}})
として呼び出したときの戻り値は,{{【 a 】},{【 b 】},{【 c 】}} である。


〔プログラム〕

○整数型配列の配列:transformSparseMatrix(整数型の二次元配列:matrix)
  整数型:i,j
  整数型配列の配列:sparseMatrix
  sparseMatrix ← {{ },{ },{ }}  /* 要素数0の配列を三つ要素にもつ配列 */
  for(i を 1 から matrix の行数 まで 1 ずつ増やす)
    for(j を 1 から matrix の列数 まで 1 ずつ増やす)
      if(matrix[i,j] が 0 でない)
        sparseMatrix[1]の末尾 に i の値を追加する
        sparseMatrix[2]の末尾 に j の値を追加する
        sparseMatrix[3]の末尾 に matrix[i,j]の値を追加する
      endif
    endfor
  endfor
  return sparseMatrix

解答群

a b c
1,2,2,3,3,4,5 1,2,3,4,5,4,5 3,2,2,1,2,3,1
1,2,2,3,3,4,5 1,2,3,4,5,4,5 3,2,2,1,3,2,1
1,2,3,4,5,4,5 1,2,2,3,3,4,5 3,2,2,1,2,3,1
1,2,3,4,5,4,5 1,2,2,3,3,4,5 3,2,2,1,3,2,1
解説を開く

正解は です。

①トレース表を作成

matlix

1 2 3 4 5
1 3 0 0 0 0
2 0 2 2 0 0
3 0 0 0 1 3
4 0 0 0 2 0
5 0 0 0 0 1

i\jを間違えないように注意!
iが行、jが列です。

(例)
matrix[2,3] = 2
matrix[3,2] = 0

i j

sparseMatrix

1 2 3

②外側1周目for(i を 1 から matrix の行数 まで 1 ずつ増やす)
③内側1周目for(j を 1 から matrix の列数 まで 1 ずつ増やす)

i (1-5) j(1-5)
=== ===
1
—- —-
1

if(matrix[i,j] が 0 でない)

i (1-5) j(1-5) matrix[i,j] が 0 でない
=== === ===
1
—- —- —-
1 matrix[1,1] ≠0
3


sparseMatrix[1]の末尾 に i の値を追加する
sparseMatrix[2]の末尾 に j の値を追加する
sparseMatrix[3]の末尾 に matrix[i,j]の値を追加する

sparseMatrix

i\j 1
1 1
2 1
3 matrix[1,1]
3

⑥内側2~5周目
matrix[1,2]、matrix[1,3]、matrix[1,4]、matrix[1,5]はいずれも0のため、sparseMatrixに値は追加されません。

(参考)matrix

i\j 1 2 3 4 5
1 3 0 0 0 0

⑦外側2周目
iが2になります。
0でないのはmatrix[2,2]とmatrix[2,3]のみです。

sparseMatrix[1]の末尾 に i の値を追加する
sparseMatrix[2]の末尾 に j の値を追加する
sparseMatrix[3]の末尾 に matrix[i,j]の値を追加する

matrix[2,2]
(2)

i\j 1 2
1 1 2
2 1 2
3 3 2

matrix[2,3]
(2)

i\j 1 2 3
1 1 2 2
2 1 2 3
3 3 2 2


以降、matrix[i,j]が0でない時だけトレースします。

matrix[3,4]
(1)

i\j 1 2 3 4
1 1 2 2 3
2 1 2 3 4
3 3 2 2 1

matrix[3,5]
(3)

i\j 1 2 3 4 5
1 1 2 2 3 3
2 1 2 3 4 5
3 3 2 2 1 3

⑨この時点で、当てはまるのはイだけです。

a b c
1,2,2,3,3,4,5 1,2,3,4,5,4,5 3,2,2,1,3,2,1

✓R404-問5 英単語(オブジェクト指向&読解)

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

任意の異なる 2 文字を c1,c2 とするとき,英単語群に含まれる英単語において,c1 の次に c2 が出現する割合を求めるプログラムである。
英単語は,英小文字だけから成る。英単語の末尾の文字が c1 である場合,その箇所は割合の計算に含めない。例えば,図に示す 4 語の英単語 “importance”, “inflation”, “information”, “innovation” から成る英単語群において,c1 を “n”,c2 を “f” とする。
英単語の末尾の文字以外に “n” は五つあり,そのうち次の文字が “f” であるものは二つである。したがって,求める割合は,2 ÷ 5 = 0.4 である。c1 と c2 の並びが一度も出現しない場合,c1 の出現回数によらず割合を 0 と定義する。

image-20260108142859649

図 4語から成る英単語群の例

プログラムにおいて,英単語群は Words 型の大域変数 words に格納されている。クラス Words のメソッドの説明を,表に示す。本問において,文字列に対する演算子 “+” は,文字列の連結を表す。また,整数に対する演算子 “÷” は,実数として計算する。

表 クラス Words のメソッドの説明

メソッド 戻り値 説明
freq(文字列型:str) 整数型 英単語群中の文字列 str の出現回数を返す。
freqE(文字列型:str) 整数型 英単語群の中で,文字列 str で終わる英単語の数を返す。

〔プログラム〕

大域:Words:words  /* 英単語群が格納されている */

/* c1 の次に c2 が出現する割合を返す */
○実数型:prob(文字型:c1,文字型:c2)
  文字列型:s1 ← c1 の 1 文字だけから成る文字列
  文字列型:s2 ← c2 の 1 文字だけから成る文字列
  if(words.freq(s1 + s2) が 0 より大きい)
    return 【   】
  else
    return 0
  endif

解答群

ア (words.freq(s1) − words.freqE(s1)) ÷ words.freq(s1 + s2)
イ (words.freq(s2) − words.freqE(s2)) ÷ words.freq(s1 + s2)
ウ words.freq(s1 + s2) ÷ (words.freq(s1) − words.freqE(s1))
エ words.freq(s1 + s2) ÷ (words.freq(s2) − words.freqE(s2))

解説を開く

①式を確認

英単語の末尾の文字以外に "n" は五つあり,そのうち次の文字が "f" であるものは二つである。したがって,求める割合は,2 ÷ 5 = 0.4 である。
上記より、
nの次がfであるもの÷末尾の文字以外のnの数とわかります。

②解答群を確認

  • ÷words.freq(s1 + s2)か、words.freq(s1 + s2)÷
  • s1とs2のどちらを使うか

ここで、freqは、英単語群中の文字列 str の出現回数を返します。
つまりwords.freq(s1 + s2)は、nの次がfであるものなので、words.freq(s1 + s2)÷であると判断できます。

①(何をするプログラムなのかを分析)

任意の異なる 2 文字を c1,c2 とするとき,英単語群に含まれる英単語において,c1 の次に c2 が出現する割合を求めるプログラムである。
英単語の末尾の文字が c1 である場合,その箇所は割合の計算に含めない。
以上より、最終的に計算するのは
c1の次にc2が出現する回数÷(c1の出現回数-c1で終わる英単語の数)とわかる。

②(選択肢を検証)
式と一致するのはウwords.freq(s1 + s2) ÷ (words.freq(s1) − words.freqE(s1))

R404-問6情報セキュリティ

製造業のA社では,ECサイト(以下,A社のECサイトをAサイトという)を使用し,個人向けの製品販売を行っている。Aサイトは,A社の製品やサービスが検索可能で,ログイン機能を有しており,あらかじめAサイトに利用登録した個人(以下,会員という)の氏名やメールアドレスといった情報(以下,会員情報という)を管理している。Aサイトは,B社のPaaSで稼働しており,PaaS上のDBMSとアプリケーションサーバを利用している。
A社は,Aサイトの開発,運用をC社に委託している。A社とC社との間の委託契約では,Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている。

最近,A社の同業他社が運営しているWebサイトで脆弱性が悪用され,個人情報が漏えいするという事件が発生した。そこでA社は,セキュリティ診断サービスを行っているD社に,Aサイトの脆弱性診断を依頼した。脆弱性診断の結果,対策が必要なセキュリティ上の脆弱性が複数指摘された。図1にD社からの指摘事項を示す。

(一) Aサイトで利用しているDBMSに既知の脆弱性があり,脆弱性を悪用した攻撃を受けるおそれがある。
(二) Aサイトで利用しているアプリケーションサーバのOSに既知の脆弱性があり,脆弱性を悪用した攻撃を受けるおそれがある。
(三) ログイン機能に脆弱性があり,Aサイトのデータベースに蓄積された情報のうち,会員には非公開の情報を閲覧されるおそれがある。

図1 D社からの指摘事項

図1中の項番(一)~(三)それぞれに対処する組織の適切な組合せを,解答群の中から選べ。

解答群

(一) (二) (三)
A社 A社 A社
A社 A社 C社
A社 B社 B社
B社 B社 B社
B社 B社 C社
B社 C社 B社
B社 C社 C社
C社 B社 B社
C社 B社 C社
C社 C社 B社
解説を開く

正解は、オ(B社,B社,C社)です。
①項番1~3について、前半部分からキーワードを拾う

項番1 DBMS
項番2 アプリケーションサーバ
項番3 ログイン機能

②問題文から、キーワードを探す
「Aサイトは,B社のPaaSで稼働しており,PaaS上のDBMSアプリケーションサーバを利用している。A社は,Aサイトの開発,運用をC社に委託している」

上記より、項番1と2は、B社。
この時点でエかオに絞られ、項番3はB社かC社とわかる。

「A社とC社との間の委託契約では,Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている。」
より、ログイン機能がWebアプリケーションプログラムの機能であるとわかれば、項番3はC社。

よって正解はオ(B社,B社,C社)です。

`Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている`とわざわざ書いてあるので、項番3はC社であると推測できます。

※以降、準備中。

令和4年度12月

✓R4問1 変数

次の記述中の【   】に入れる正しい答えを,解答群の中から選べ。
プログラムを実行すると,“【   】”と出力される。


〔プログラム〕

整数型:x ← 1
整数型:y ← 2
整数型:z ← 3

x ← y
y ← z
z ← x

y の値 と z の値 をこの順にコンマ区切りで出力する

解答群
ア 1,2
イ 1,3
ウ 2,1
エ 2,3
オ 3,1
カ 3,2

✓R4問2 fizzBuzz

次のプログラム中の【a】~【c】に入れる正しい答えの組合せを、解答群の中から選べ。

関数fizzBuzzは、引数で与えられた値が、3で割り切れて5で割り切れない場合は「3で割り切れる」を、5で割り切れて3で割り切れない場合は「5で割り切れる」を、3と5で割り切れる場合は「3と5で割り切れる」を返す。それ以外の場合は「3でも5でも割り切れない」を返す。

○ 文字列型: fizzBuzz(整数型: num)
文字列型: result
if (numが 【a】 で割り切れる)
  result ← "【a】 で割り切れる"
elseif (numが 【b】 で割り切れる)
  result ← "【b】 で割り切れる"
elseif (numが 【c】 で割り切れる)
  result ← "【c】 で割り切れる"
else
  result ← "3でも5でも割り切れない"
endif
return result
a b c
3 3と5 5
3 5 3と5
3と5 3 5
5 3 3と5
5 3と5 3
解説を開く

正解はウです。
条件分岐は、細かい(厳しい)条件ほど上に書きます。
今回、最も細かい条件は3と5で割り切れるです。
3と5 が一番上の分岐である【a】に入っている、ウが正解です。

Point:上の方に書いてある条件分岐ほど、条件が細かくなる

条件分岐は、最初の条件が一番細かく、後の方ほどシンプルになる傾向があります。
2つめ以降の条件は「それより前の条件を満たしていない」ことも前提になるからです。
(イメージ)

この順番を誤って、より細かい条件の分岐を後にしてしまうと、細かい条件に合致するものも到達できなくなります。(☆言い方)
(イメージ)

Memo:浮いている選択肢は正解の可能性大
aに注目すると、ウだけが選択肢として浮いています。
他の選択肢3,5は2つずつあるのに3と5はウしかありません。

a
3
3
3と5
5
5

このように浮いている選択肢がある場合、正解の可能性が高いです。

✓R4問3 makeNewArray(配列&繰り返し)

次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる。

関数 makeNewArray は,要素数 2 以上の整数型の配列を引数にとり,整数型の配列を返す関数である。
関数 makeNewArraymakeNewArray({3, 2, 1, 6, 5, 4}) として呼び出したとき,戻り値の配列の要素番号 5 の値は【 】となる。

○ 整数型の配列: makeNewArray(整数型の配列: in)
整数型の配列: out ← {}    // 要素数0の配列
整数型: i, tail
outの末尾に in[1] の値を追加する
for (i を 2 から inの要素数 まで 1 ずつ増やす)
    tail ← out[outの要素数]
    outの末尾に (tail + in[i]) の結果を追加する
endfor
return out

解答群
ア 5
イ 6
ウ 9
エ 11
オ 12
カ 17
キ 21

解説を開く

正解はカ17です。

求められているのは戻り値ではなく、`戻り値の配列の要素番号 5 の値`です。
`out[5]`の値が判明するまでトレースすればOK、ということをトレース前に確認しておきます。

①配列表を作成
in

1 2 3 4 5 6
3 2 1 6 5 4

outの末尾に in[1] の値を追加する
out

1
3

繰り返し処理に気を取られ、途中の処理を見落とやすいです。気を付けましょう。

③トレース表を作成

i (2~6) outの末尾に(out[outの要素数] + in[i])
2

以下2行を1行にまとめています。

      tail ← out[outの要素数]
      outの末尾に (tail + in[i]) の結果を追加する

実際のトレース時は `o[末]にo[要]+in[i]`など、わかる形で省略して書きましょう。

④iに注目すると、以下のように トレースできます。

i (2~6) outの末尾に(out[outの要素数] + in[i])
2 o[末]にo[要]+in[2]
3 o[末]にo[要]+in[3]
4 o[末]にo[要]+in[4]
5 o[末]にo[要]+in[5]
6 o[末]にo[要]+in[6]

(計算結果)

i (2~6) outの末尾に(out[outの要素数] + in[i])
2 o[末]にo[要]+in[2]
   3 + 2
   5
3 o[末]にo[要]+in[3]
   5 + 1
   6
4 o[末]にo[要]+in[4]
   6 + 6
   12
5 o[末]にo[要]+in[5]
   12 + 5
   17
6 o[末]にo[要]+in[6]

`outの末尾`や`out[outの要素数]`が何を指すのか、丁寧にトレースしましょう。

out

1 2 3 4 5
3 5 6 12 17

out[5]は、17(カ)です。

求めるのは`戻り値の配列の要素番号 5 の値`なので、iが6になるまで繰り返す必要はありません。

(式をまとめずに、分けてトレースした場合)

| i(2~6) | tail | outの末尾に(tail + in[i]) |
| :—–: | :—————: | :—————————————: |
| 2 | ~~out[1]~~
3 | o[末]に(tail + in[2])
3 + 2
5 |
| 3 | ~~out[2]~~
5 | o[末]に(tail + in[3])
5 + 1
6 |
| 4 | out[3]
6 | o[末]に(tail + in[4])
6 + 6
12 |
| 5 | out[4]
12 | o[末]に(tail + in[5])
12 + 5
17 |

Point:何が問われているのかをまず確認する

本番では、実行結果以外も問われることがあります。

  • 配列の○番目の要素の値
  • 特定の行を何回繰り返したか
  • 条件判定が何回真になるか

途中のトレースを省略するなど、より効率的に正解できます。
「何が問われているのか」を始めに確認するようにしましょう。

Memo:配列[配列の要素数]は、配列の末尾の値を指す

out[outの要素数]のように、配列[配列の要素数]は、配列の末尾の値を指します。
outの要素数が1ならout[1]、4つならout[4]の値です。

out

1 2 3 4 5 6
3 5 6 12 17 21

上記の場合、out[outの要素数]はout[6]、つまり末尾の値21です。
登場頻度は少ないので、覚えなくてOK。知っているかどうかよりも、トレースしながら「つまり、末尾の値だな」と理解できる(あるいは、理解できなかったとしてもトレースによって正解を導ける)ことが重要です。

Memo:(別解)配列outの値は、その要素数までの累計

(アルゴリズムの本質的な話しで、合格にここまでの理解は必要ありません。おまけ程度に聞いてください。エンジニアを目指している方は理解しておくと、プログラミング学習の際にスムーズです。)

トレース表のとおり、out[]の値には、以下の計算式が成り立ちます。

out 計算式
out[2] out[1] + in[2]
out[3] out[2] + in[3]

さらに、out[1]には、in[1]が格納されています。
それも表に加えると、以下となります。

out 計算式
out[1] in[1]
out[2] out[1] + in[2]
out[3] out[2] + in[3]

out[1]はin[1]なので、out[2]のout[1]+in[2]は、in[1]+in[2]に置き換えられます。
同様に、out[2]+in[3]は、in[1]+in[2]+in[3]です。
まとめると、以下のように整理できます。

out 計算式 計算式の内訳
out[1] in[1]
out[2] out[1]+ in[2] in[1] + in[2]
out[3] out[2]+ in[3] in[1] + in[2] + in[3]
out[4] out[3]+ in[4] in[1] + in[2] + in[3] + in[4]
out[5] out[4]+ in[5] in[1] + in[2] + in[3] + in[4] + in[5]
out[6] out[5]+ in[6] in[1] + in[2] + in[3] + in[4] + in[5] + in[6]

つまり、out[x]には、in[1]からin[x]までの累計値が格納されています。
out[5]はin[1]からin[5]までの累計値なので、inの配列が{3, 2, 1, 6, 5, 4}であれば、5番目までの累計値3+2+1+6+5=17が答えです。

✓R4問4 最大公約数

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

関数 gcd は,引数で与えられた二つの正の整数 num1 と num2 の最大公約数を,
次の (1)〜(3) の性質を利用して求める。

(1)num1 と num2 が等しいとき,num1 と num2 の最大公約数は num1 である。
(2)num1 が num2 より大きいとき,num1 と num2 の最大公約数は,(num1 − num2) と num2 の最大公約数と等しい。
(3)num2 が num1 より大きいとき,num1 と num2 の最大公約数は,(num2 − num1) と num1 の最大公約数と等しい。

○ 整数型: gcd(整数型: num1, 整数型: num2)
    整数型: x ← num1
    整数型: y ← num2

    【 a 】

      if ( 【 b 】 )
          x ← x − y
      else
          y ← y − x
      endif

    【 c 】

    return x
a b c
if (x ≠ y) x < y endif
if (x ≠ y) x > y endif
while (x ≠ y) x < y endwhile
while (x ≠ y) x > y endwhile
解説を開く

①解答群の検証

aとcはセットになっており、問われているのはifかwhileかです。
bはx>yなのか、x<yなのかです。

②【a】と【c】

(1)num1 と num2 が等しいとき,num1 と num2 の最大公約数は num1 である。をプログラムに合わせて書き換えると、xとyが等しいとき、最大公約数はxである。となります。
xとyが等しい時に、xをreturnするを実現するには、等しくなるまで繰り返す(等しくない間繰り返す)必要があります。よってwhile(x≠y)です。

1回の`x-y`(あるいはy-x)では求められないことを試すのも手です。
例えば、6と2の最大公約数は2です。1回だけの処理では、戻り値xは4となり、最大公約数を求められていません。

②【b】

b内で行われている処理は x←x-yです。
問題文(2)を、xとyに書き換えると、x>yのとき、(中略)、x-y(以下略)となります。
よって【b】はx>yです。

x < y のときに x-y を計算すると、xがマイナスの値になってしまいます。(最大公約数としてxがreturnされるので、xがマイナスになるのは不適切)
よって、x

>Point:変数名に置き換える
>
>今回の`x←num1`や`y←num2`のように、間違えやすくするために、問題文とプログラムで変数の名前を変えている場合があります。
>問題文と変数名を一致させるために、用紙上に整理し直してから解きましょう。
>より短い方で統一した方が、書く手間が省けます。(今回の場合、num1・num2よりx・yの方が短いので、x・yで統一)

✓R4問5 数学(pow)

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

関数 calc は,正の実数 xy を受け取り, √(x²+y²) の計算結果を返す。関数 calc が使う関数 pow は,第1引数として正の実数 a を,第2引数として実数 b を受け取り,ab 乗の値を実数型で返す。


〔プログラム〕

○実数型:calc(実数型:x,実数型:y)
 return 【   】

解答群

ア (pow(x,2) + pow(y,2)) ÷ pow(2,0.5)
イ (pow(x,2) + pow(y,2)) ÷ pow(x,y)
ウ pow(2,pow(x,0.5)) + pow(2,pow(y,0.5))
エ pow(pow(pow(2,x),y),0.5)
オ pow(pow(x,2) + pow(y,2),0.5)
カ pow(x,2) × pow(y,2) ÷ pow(x,y)
キ pow(x,y) ÷ pow(2,0.5)

解説を開く

アかオまでは絞れる。
「0.5乗が平方根なのでは・・?」と仮説できれば、オ

✓R4問6 ビット演算

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

関数 rev は 8 ビット型の引数 byte を受け取り,ビットの並びを逆にした値を返す。
例えば,関数 rev を rev(01001011) として呼び出すと,戻り値は 11010010 となる。

なお,演算子 ∧ はビット単位の論理積,演算子 ∨ はビット単位の論理和,演算子 >> は論理右シフト,演算子 << は論理左シフトを表す。
例えば,value >> n は value の値を n ビットだけ右に論理シフトし,value << n は value の値を n ビットだけ左に論理シフトする。

○ 8ビット型: rev(8ビット型: byte)
    8ビット型: rbyte ← byte
    8ビット型: r ← 00000000
    整数型: i
    for (i を 1 から 8 まで 1 ずつ増やす)
        【 】
    endfor
    return r

解答群


r ← (r << 1) ∨ (rbyte ∧ 00000001)
rbyte ← rbyte >> 1


r ← (r << 7) ∨ (rbyte ∧ 00000001)
rbyte ← rbyte >> 7


r ← (rbyte << 1) ∨ (rbyte >> 7)
rbyte ← r


r ← (rbyte >> 1) ∨ (rbyte << 7)
rbyte ← r

解説を開く

正解はアです。

まずfor文は、8回繰り返されます。
処理対象は8ビットなので、1ビットずつ処理されます。

解答群を見ると、1ビットずつ処理していそうなのはアです。
アが何をしているのか、詳しく確認します。

r ← (r << 1) ∨ (rbyte ∧ 00000001)
rbyte ← rbyte >> 1

左に1ビット論理シフトしたrと、rbyteの下位1ビットを、rに代入しています。

i r rbyte
00000000 01001011
1 (00000000 << 1) ∨ (rbyte ∧ 00000001)
00000001
rbyte >> 1
00100101
2 (00000001 << 1) ∨ (rbyte ∧ 00000001)
00000010
rbyte >> 1
00010010

1周目はrは00000000なので、
r←(00000000 << 1) ∨ (rbyte ∧ 00000001)
rbyte ← rbyte >> 1

2周目
r←(00000001 << 1) ∨ (rbyte ∧ 00000001)

✓R4問7 再帰(階乗)

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

関数 factorial は非負の整数 n を引数にとり,その階乗を返す関数である。
非負の整数 n の階乗は n が 0 のときに 1 になり,それ以外の場合は 1 から n までの整数を全て掛け合わせた数となる。

〔プログラム〕

○整数型:factorial(整数型:n)
 if(n = 0)
  return 1
 endif

 return 【   】

解答群

ア (n − 1) × factorial(n)
イ factorial(n − 1)
ウ n
エ n × (n − 1)
オ n × factorial(1)
カ n × factorial(n − 1)

解説を開く

正解はカn × factorial(n − 1)です。


1からnまでの整数すべてを掛け合わせたとあるため、繰り返しか再帰によって1✕2✕3...✕n(もしくはn✕(n-1)✕(n-2)...✕1)と繰り返す必要があります。

プログラム上、繰り返し処理はないため、再帰を行いながら掛け算を行っているア、オ、カに絞られます。


再帰する場合、元の引数を変化させて呼び出さないと、無限ループになってしまいます。
そのため、nをそのまま引数にしているア、固定値1のオが候補から外れます。これでカn × factorial(n − 1)に一択に絞られます。

(③トレースで検証)
カを正解として、n=4としてトレースすると、以下となります。

4✕factorial(3)
  3✕factorial(2)
    2✕factorial(1)
      1

4の階乗24になるので、正しいです。

Memo:再帰は似たような問題が出る可能性大

再帰を使った階乗は、プログラミング学習では定番です。
他に問題として使えそうなものがあまりない(穴埋めさせると難しくなりすぎてしまう)ので、似たような問題が出る可能性が高いです。

✓R4問8 優先度付きキュー

次の記述中の【   】に入れる正しい答えを,解答群の中から選べ。

優先度付きキューを操作するプログラムである。優先度付きキューとは扱う要素に優先度を付けたキューであり,要素を取り出す際には優先度の高いものから順番に取り出される。クラス PrioQueue は優先度付きキューを表すクラスである。クラス PrioQueue の説明を図に示す。ここで,優先度は整数型の値 1,2,3 のいずれかであり,小さい値ほど優先度が高いものとする。

手続 prioSched を呼び出したとき,出力は【   】の順となる。


【コンストラクタ】

コンストラクタ 説明
PrioQueue() 空の優先度付きキューを生成する。

【メソッド】

メソッド名 戻り値 説明
enqueue(文字列型:s,整数型:prio) なし 優先度付きキューに,文字列 s を要素として,優先度 prio で追加する。
dequeue() 文字列型 優先度付きキューからキュー内で最も優先度の高い要素を取り出して返す。
最も優先度の高い要素が複数あるときは,そのうちの最初に追加された要素を一つ取り出して返す。
size() 整数型 優先度付きキューに格納されている要素の個数を返す。

図 クラス PrioQueue の説明

〔プログラム〕

○prioSched()
 PrioQueue:prioQueue ← PrioQueue()
 prioQueue.enqueue("A",1)
 prioQueue.enqueue("B",2)
 prioQueue.enqueue("C",2)
 prioQueue.enqueue("D",3)
 prioQueue.dequeue() /* 戻り値は使用しない /
 prioQueue.dequeue() / 戻り値は使用しない /
 prioQueue.enqueue("D",3)
 prioQueue.enqueue("B",2)
 prioQueue.dequeue() / 戻り値は使用しない /
 prioQueue.dequeue() / 戻り値は使用しない */
 prioQueue.enqueue("C",2)
 prioQueue.enqueue("A",1)
 while(prioQueue.size() が 0 と等しくない)
  prioQueue.dequeue() の戻り値を出力
 endwhile

解答群

ア ”A”,”B”,”C”,”D”
イ ”A”,”B”,”D”,”D”
ウ ”A”,”C”,”C”,”D”
エ ”A”,”C”,”D”,”D”

解説を開く

 prioQueue.enqueue("A",1)
 prioQueue.enqueue("B",2)
 prioQueue.enqueue("C",2)
 prioQueue.enqueue("D",3)
優先度 1 2 2 3
文字列 A B C D

 prioQueue.dequeue() /* 戻り値は使用しない /
 prioQueue.dequeue() / 戻り値は使用しない /
優先度 1 2 2 3
文字列 A B C D

上記のようにwhileの行までトレースすると、以下となります。

優先度 1 2 2 3 3 2 2 1
文字列 A B C D D B C A

この状態で0になるまでprioQueue.dequeue()を実行すると、出力順はA,B,D,D(イ)となります。

✓R4問9 再帰(2分木)

次の記述中の【   】に入れる正しい答えを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる。

手続 order は,図の 2 分木の,引数で指定した節を根とする部分木をたどりながら,全ての節番号を出力する。大域の配列 tree が図の 2 分木を表している。
配列 tree の要素は,対応する節の子の節番号を,左の子,右の子の順に格納した配列である。例えば,配列 tree の要素番号 1 の要素は,節番号 1 の子の節番号から成る配列であり,左の子の節番号 2,右の子の節番号 3 を配列 {2,3} として格納する。

手続 order を order(1) として呼び出すと,【   】の順に出力される。

image-20260109105105295
注記1 ○の中の値は節番号である。
注記2 子の節が一つの場合は,左の子の節とする。
図 プログラムが扱う 2 分木

〔プログラム〕

大域:整数型配列の配列:tree ←{{2, 3}, {4, 5}, {6, 7}, {8, 9},
                             {10, 11}, {12, 13}, {14}, {}, {}, {},
                             {}, {}, {}, {}}   // {} は要素数 0 の配列

○order(整数型:n)
  if (tree[n] の要素数 が 2 と等しい)
    order(tree[n][1])
    n を出力
    order(tree[n][2])
  elseif (tree[n] の要素数 が 1 と等しい)
    order(tree[n][1])
    n を出力
  else
    n を出力
  endif

解答群

ア 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
イ 1, 2, 4, 8, 9, 5, 10, 11, 3, 6, 12, 13, 7, 14
ウ 8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7
エ 8, 9, 4, 10, 11, 5, 2, 12, 13, 6, 14, 7, 3, 1

解説を開く

①トレース表を作成

tree

1 2
1 2 3
2 4 5
3 6 7
4 8 9
5 10 11
6 12 13
7 14
8
~
14

8以降は{}(要素数0の配列)なので、省略して記載しています。

②order(1)を、nに1を代入するだけの形でトレースすると、以下となります。

od(1)
order(tree[1] [1])
2
1を出力
order(tree[1] [2])

③さらに、order(2)をトレースすると、以下となります。

od(1)) od(2)
order(tree[1] [1])
2
order(tree[2] [1])
2を出力
order(tree[2] [2])
1を出力
order(tree[1] [2])

(さらにod2をトレースした結果)

od(1) od(2) od(4) od(8) “8”
“1” “2” “4”
od(9) “9”
od(5)
od(3)

ここまでで、出力されているのは”8″,”4″,”9″,”2″です。
よって正解はウ 8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7 です。

Memo:検索パターンについて解説
知っていれば途中までトレースすれば回答がわかる、程度に

R4問10リスト

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

手続 delNode は,単方向リストから,引数 pos で指定された位置の要素を削除する手続である。
引数 pos は,リストの要素数以下の正の整数とする。
リストの先頭の位置を 1 とする。

クラス ListElement は,単方向リストの要素を表す。
クラス ListElement のメンバ変数の説明を表に示す。
ListElement 型の変数はクラス ListElement のインスタンスの参照を格納するものとする。
大域変数 listHead には,リストの先頭要素の参照があらかじめ格納されている。


表 クラス ListElement のメンバ変数の説明

メンバ変数 説明
val 文字型 要素の値
next ListElement 次の要素の参照(次の要素がないときの状態は未定義)

〔プログラム〕

大域:ListElement: listHead   // リストの先頭要素が格納されている

○delNode(整数型: pos)   /* pos は,リストの要素数以下の正の整数 */
  ListElement: prev
  整数型: i

  if (pos が 1 と等しい)
    listHead ← listHead.next
  else
    prev ← listHead
    /* pos が 2 と等しいときは繰返し処理を実行しない */
    for (i を 2 から pos − 1 まで 1 ずつ増やす)
      prev ← prev.next
    endfor

    prev.next ← 【   】
  endif

解答群

ア listHead
イ listHead.next
ウ listHead.next.next
エ prev
オ prev.next
カ prev.next.next

✓R4問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, 6, 3, 1, 4, 5}です。


足りない内訳があれば、足す

✓R4問12読解

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

関数simRatioは,引数として与えられた要素数1以上の二つの文字型の配列s1とs2を比較し,要素数が等しい場合は,配列の並びがどの程度似ているかを示す指標として,(要素番号が同じ要素の文字同士が一致する要素の組の個数
÷ s1の要素数)を返す。
すべて一致すれば戻り値は1,一致しなければ0,要素数が異なる場合は
−1を返す。

表 関数 simRatio に与える s1,s2 及び戻り値の例

s1 s2 戻り値
{ “a”, “p”, “p”, “l”, “e” } { “a”, “p”, “p”, “l”, “e” } 1
{ “a”, “p”, “p”, “l”, “e” } { “a”, “p”, “r”, “i”, “l” } 0.4
{ “a”, “p”, “p”, “l”, “e” } { “m”, “e”, “l”, “o”, “n” } 0
{ “a”, “p”, “p”, “l”, “e” } { “p”, “e”, “n” } −1
○ 実数型: simRatio(文字型の配列: s1, 文字型の配列: s2)
整数型: i, cnt ← 0
if (s1の要素数 ≠ s2の要素数)
  return −1
endif
for (iを1からs1の要素数 まで1ずつ増やす)
  if (【   】)
    cnt ← cnt + 1
  endif
endfor
return cnt ÷ s1の要素数 /* 実数として計算する*/

ア s1\[i\] ≠ s2\[cnt\]
イ s1\[i\] ≠ s2\[i\]
ウ s1\[i\] = s2\[cnt\]
エ s1\[i\] = s2\[i\]

解説を開く

正解はイs1\[i\] ≠ s2\[i\]です。

①式と戻り値を確認
問題文から要素番号が同じ要素の文字同士が一致する要素の組の個数÷ s1の要素数の式が戻り値であることを確認しておきます。

②解答群を確認
どんな選択肢があるのかを確認します。

  • =か≠か
  • s2[i]かs2[cnt]か

の2つが問われていることがわかります。

③何を求められているのかを確認
今回問われているのはIF(【 】)の中に入る条件です。
IF文内の処理にはcnt ← cnt + 1があるので、【】が真の時に、cntを増やす、とわかります。

④cntが何を指すのかを確認
cntがその後どこで使われているかを見るとreturn cnt ÷ s1の要素数です。
戻り値なので、①で確認した式と照らし合わせます。

問題文 要素番号が同じ要素の文字同士が一致する要素の組の個数 ÷ s1の要素数
プログラム cnt ÷ s1の要素数

cntは「要素番号が同じ要素の文字同士が一致する要素の組の個数」を指すことがわかります。
つまり要素番号が同じ要素の文字同士が一致する時にcntを増やせば良いです。

合致する選択肢はエs1[i] = s2[i]です。

Point:プログラム全体を理解する必要なし

正解さえわかれば、プログラム全体を理解する必要はありません。
今回であれば

  • 表 関数 simRatio に与える s1,s2 及び戻り値の例
  • 要素数が異なる場合は−1を返す。

などの情報や、「プログラムのどこがそれに該当するのか」は解答に必要ありません。
正解することが一番の目的であることを忘れずに。情報の取捨選択は、実務でも重要です。

✓R4問13(応用-無限ループ)

次の記述中の【   】に入れる正しい答えを,解答群の中から選べ。ここで,配列の要素番号は 1 から始まる。

関数 search は,引数 data で指定された配列に,引数 target で指定された値が含まれていればその要素番号を返し,含まれていなければ −1 を返す。data は昇順に整列されており,値に重複はない。

関数 search には不具合がある。例えば,data の【   】場合は,無限ループになる。

〔プログラム〕

○ 整数型:search(整数型の配列:data,整数型:target)
  整数型:low,high,middle

  low ← 1
  high ← data の要素数

  while(low ≤ high)
    middle ←(low + high)÷ 2 の商
    if(data[middle] < target)
      low ← middle
    elseif(data[middle] > target)
      high ← middle
    else
      return middle
    endif
  endwhile

  return −1

解答群

ア 要素数が 1 で,target がその要素の値と等しい
イ 要素数が 2 で,target が data の先頭要素の値と等しい
ウ 要素数が 2 で,target が data の末尾要素の値と等しい
エ 要素に −1 が含まれている

(全部トレースすればわかる、けど・・)

✓R4問14

次の記述中の〔  〕に入れる正しい答えを,解答群の中から選べ。
ここで、配列の要素番号は 1 から始まる。

要素数が 1 以上で,昇順に整列済みの配列を基に,配列を特徴づける五つの値を返すプログラムである。
関数 summarize を summarize({0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1}) として呼び出すと,戻り値は〔  〕である。

〔プログラム〕

○実数型: findRank(実数型の配列: sortedData, 実数型: p)
    整数型: i
    i ← (p × (sortedData の要素数 − 1)) の小数点以下を切り上げた値
    return sortedData[i + 1]

○実数型の配列: summarize(実数型の配列: sortedData)
    実数型の配列: rankData ← {}   /* 要素数0の配列 */
    実数型の配列: p ← {0, 0.25, 0.5, 0.75, 1}

    整数型: i
    for (i を 1 から p の要素数 まで 1 ずつ増やす)
        rankData の末尾に findRank(sortedData, p[i]) の戻り値を追加する
    endfor
    return rankData

〔解答群〕
ア {0.1, 0.3, 0.5, 0.7, 1}
イ {0.1, 0.3, 0.5, 0.8, 1}
ウ {0.1, 0.2, 0.3, 0.7, 1}
エ {0.1, 0.3, 0.4, 0.6, 1}
オ {0.1, 0.3, 0.4, 0.7, 1}
カ {0.1, 0.3, 0.4, 0.8, 1}
キ {0.1, 0.4, 0.6, 0.7, 1}
ク {0.1, 0.4, 0.6, 0.8, 1}

解説を開く

①配列表の作成
sortedData

1 2 3 4 5 6 7 8 9 10
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

p

1 2 3 4 5
0 0.25 0.5 0.75 1

②トレース表の作成

i i-f p

③1周目i を 1 から p の要素数 まで 1 ずつ増やす

i (1-5) i-f p
1

rankData の末尾に findRank(sortedData, p[i]) の戻り値を追加するfindRank(sortedData, p[i])をトレースします。
定義上はfindRank(sortedData, p)なので、pにp[i]を代入します。

i (1-5) i-f p
1 p[1]
0

③(findRank)i ← (p × (sortedData の要素数 − 1)) の小数点以下を切り上げた値
i ←(0✕ 10-1)の小数点以下切り上げ
i ← 0

i (1-5) i-f p
1 (0*(10-1))
0
p[1]
0

④(findRank)return sortedData[i + 1]
(summarize)rankData の末尾に findRank(sortedData, p[i]) の戻り値を追加する
なので、

rankData

1
sortedData[0+1]
0.1

⑥(2周目)

i (1-5) i-f p
1 (0*(10-1))
0
p[1]
0
—- —- —-
2 (0.25*(10-1))
3
p[2]
0.25

(findRank)return sortedData[i + 1]
(summarize)rankData の末尾に findRank(sortedData, p[i]) の戻り値を追加する

1 2
sortedData[0+1]
0.1
sortedData[3+1]
0.4

⑦(3~4週目)

i (1-5) i-f p
1 (0*(10-1))
0
p[1]
0
—- —- —-
2 (0.25*(10-1))
3
p[2]
0.25
—- —- —-
3 (0.5*(10-1))
5
p[3]
0.5
—- —- —-
4 (0.75*(10-1))
7
p[4]
0.75

rankData

1 2 3 4
sortedData[0+1]
0.1
sortedData[3+1]
0.4
sortedData[5+1]
0.6
sortedData[7+1]
0.8

最後に求めるのはrankDataの値です。
ここまでで合致するのはク{0.1, 0.4, 0.6, 0.8, 1} のみです。

✓R4問15○×ゲームの問題

問15 次の記述中の【a】と【b】に入れる正しい答えの組合せを,解答群の中から選べ。

三目並べにおいて自分が勝利する可能性が最も高い手を決定する。次の手順で,ゲームの状態遷移を木構造として表現し,根以外の各節の評価値を求める。その結果,根の子の中で最も評価値が高い手を,最も勝利する可能性が高い手とする。自分が選択した手を〇で表し,相手が選択した手を×で表す。

〔手順〕
(1) 現在の盤面の状態を根とし,勝敗がつくか,引き分けとなるまでの考えられる全ての手を木構造で表現する。

(2) 葉の状態を次のように評価する。

解説を開く

① 自分が勝ちの場合は10
② 自分が負けの場合は−10
③ 引き分けの場合は0

(3) 葉以外の節の評価値は,その節の全ての子の評価値を基に決定する。
① 自分の手番の節である場合,子の評価値で最大の評価値を節の評価値とする。
② 相手の手番の節である場合,子の評価値で最小の評価値を節の評価値とする。

ゲームが図の最上部にある根の状態のとき,自分が選択できる手は三つある。そのうちAが指す子の評価値は【a】であり,Bが指す子の評価値は【b】である。


(図 三目並べの状態遷移)

a b
0 −10
0 0
10 −10
10 0

✓R4問16 ビット

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

Unicode の符号位置を,UTF-8 の符号に変換するプログラムである。本問で数値の
後ろに“(16)”と記載した場合は,その数値が 16 進数であることを表す。

Unicode の各文字には,符号位置と呼ばれる整数値が与えられている。UTF-8 は,
Unicode の文字を符号化する方式の一つであり,符号位置が 800(16) 以上 FFFF(16)
以下の文字は,次のように 3 バイトの値に符号化する。

3 バイトの長さのビットパターンを 1110xxxx 10xxxxxx 10xxxxxx とする。ビット
パターンの下線の付いた“x”の箇所に,符号位置を 2 進数で表した値を右詰めで格
納し,余った“x”の箇所に,0 を格納する。この 3 バイトの値が UTF-8 の符号であ
る。

例えば,ひらがなの“あ”の符号位置である 3042(16) を 2 進数で表すと
11000001000010 である。これを,上に示したビットパターンの“x”の箇所に右詰め
で格納すると,1110xx11 10000001 10000010 となる。余った二つの“x”の箇所に 0
を格納すると,“あ”の UTF-8 の符号 11100011 10000001 10000010 が得られる。

関数 encode は,引数で渡された Unicode の符号位置を UTF-8 の符号に変換し,先
頭から順に 1 バイトずつ要素に格納した整数型の配列を返す。encode には,引数と
して,800(16) 以上 FFFF(16) 以下の整数値だけが渡されるものとする。

〔プログラム〕

○ 整数型の配列: encode(整数型: codePoint)
    /* utf8Bytes の初期値は,ビットパターンの “x” を全て 0 に置き換え、8桁ごとに区切って,それぞれを 2進数とみなしたときの値 */
    整数型の配列: utf8Bytes ← {224, 128, 128}
    整数型: cp ← codePoint
    整数型: i
    for (i を utf8Bytes の要素数 から 1 まで 1 ずつ減らす)
        utf8Bytes[i] ← utf8Bytes[i] + (cp ÷ 【 】 の余り)
        cp ← cp ÷ 【 】 の商
    endfor
    return utf8Bytes

解答群

ア ((4 − i) × 2)
イ (2 の (4 − i) 乗)
ウ (2 の i 乗)
エ (i × 2)
オ 2
カ 6
キ 16
ク 64
ケ 256

解説を開く

①【】の余り、【】の商とあるため、何ビットずつ処理するのかがわかれば解けるとわかります。

②問題文より

1110xxxx 10xxxxxx 10xxxxxxのxの部分に、11 000001 000010を右から順に格納します。
右から6ビットずつ処理するので、【】には64(2の6乗)が入ります。

最後は2ビット(11)だけになりますが、÷64の余りで取得でき(000011を取れる)、÷64の商は0になるので、問題ありません。

(参考:【】に16を入れた場合のトレース)

utf8Bytes

1 2 3
11100000 10000000 10000000
i(1~3) cp utf8Bytes[i] + (cp ÷ 64 の余り)
11000001000010
3 11000001 10000000+000010(下位6ビット)
2 11 10000000+000001(下位6ビット)
1 0 11100000+000011(下位6ビット)

Memo整数型の配列: bitSize ← {4, 6, 6}

for (i を utf8Bytes の要素数 から 1 まで 1 ずつ減らす)
utf8Bytes[i] ← utf8Bytes[i] + (cp ÷ (2 の bitSize[i] 乗) の余り)
cp ← cp ÷ (2 の bitSize[i] 乗) の商
endfor

R4問17(情報セキュリティ)

製造業のA社では,ECサイト(以下,A社のECサイトをAサイトという)を使用し,個人向けの製品販売を行っている。Aサイトは,A社の製品やサービスが検索可能で,ログイン機能を有しており,あらかじめAサイトに利用登録した個人(以下,会員という)の氏名やメールアドレスといった情報(以下,会員情報という)を管理している。Aサイトは,B社のPaaSで稼働しており,PaaS上のDBMSとアプリケーションサーバを利用している。
A社は,Aサイトの開発,運用をC社に委託している。A社とC社との間の委託契約では,Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている。

最近,A社の同業他社が運営しているWebサイトで脆弱性が悪用され,個人情報が漏えいするという事件が発生した。そこでA社は,セキュリティ診断サービスを行っているD社に,Aサイトの脆弱性診断を依頼した。脆弱性診断の結果,対策が必要なセキュリティ上の脆弱性が複数指摘された。図1にD社からの指摘事項を示す。

項番1 Aサイトで利用しているアプリケーションサーバのOSに既知の脆弱性があり,脆弱性を悪用した攻撃を受けるおそれがある。
項番2 Aサイトにクロスサイトスクリプティングの脆弱性があり,会員情報を不正に取得されるおそれがある。
項番3 Aサイトで利用しているDBMSに既知の脆弱性があり,脆弱性を悪用した攻撃を受けるおそれがある。

図 1 D 社からの指摘事項

設問 図1中の各項番それぞれに対処する組織の適切な組合せを,解答群の中から選べ。

解答群

項番1 項番2 項番3
A社 A社 A社
A社 A社 C社
A社 B社 B社
B社 B社 B社
B社 B社 C社
B社 C社 B社
B社 C社 C社
C社 B社 B社
C社 B社 C社
C社 C社 B社
解説を開く

(解説)

①項番1から3について、キーワードを拾う

項番1 アプリケーションサーバ
項番2 クロスサイトスクリプティング
項番3 DBMS

②問題文から、キーワードを探す
Aサイトは,B社のPaaSで稼働しており,PaaS上のDBMSアプリケーションサーバを利用している。A社は,Aサイトの開発,運用をC社に委託している。A社とC社との間の委託契約では,Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている。

項番1と3は、B社。この時点でエかカに絞られ、項番2はBかCとわかる。
あとはクロスサイトスクリプティングがアプリケーションプログラムの脆弱性であるとわかれば、項番2はC社とわかる

`Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている`とわざわざ書いてあるので、項番2はC社であると推測できます。

正解はカです。

B社:DBMSとアプリケーションサーバー

項番1にアプリケーションサーバー、項番3にDBMSがあるので、B社です。
この時点で、エかカに絞られます。

A社とC社との間の委託契約では,Webアプリケーションプログラムの脆弱性対策は,C社が実施するとしている。
とあり、項番2はC社です。

わざわざ書いてあることもヒントになります。

R4問18

A社はIT開発を行っている従業員1,000名の企業である。総務部50名,営業部50名で,ほかは開発部に所属している。開発部員の9割は客先に常駐している。現在,A社におけるPCの利用状況は図1のとおりである。

図1 A社におけるPCの利用状況

1 A社のPC
・総務部員,営業部員及びA社オフィスに勤務する開発部員には,会社が用意したPC(以下,A社PCという)を一人1台ずつ貸与している。
・客先常駐開発部員には,A社PCを貸与していないが,代わりに客先常駐開発部員がA社オフィスに出社したときに利用するための共用PCを用意している。

2 客先常駐開発部員の業務システム利用
・客先常駐開発部員が休暇申請,経費精算などで業務システムを利用するためには共用PCを使う必要がある。

3 A社のVPN利用
・A社には,VPNサーバが設置されており,営業部員が出張時にA社PCからインターネット経由で社内ネットワークにVPN接続し,業務システムを利用できるようになっている。規則で,VPN接続にはA社PCを利用すると定められている。


A社では,客先常駐開発部員が業務システムを使うためだけにA社オフィスに出社するのは非効率的であると考え,客先常駐開発部員に対して個人所有PCの業務利用(BYOD)とVPN接続の許可を検討することにした。

設問 客先常駐開発部員に,個人所有PCからのVPN接続を許可した場合に,増加する又は新たに生じると考えられるリスクを二つ挙げた組合せは,次のうちどれか。解答群のうち,最も適切なものを選べ。

(-)VPN接続が増加し,可用性が損なわれるリスク
(二)客先常駐開発部員がA社PCを紛失するリスク
(三)客先常駐開発部員がフィッシングメールのURLをクリックして個人所有PCがマルウェアに感染するリスク
(四)総務部員が個人所有PCをVPN接続するリスク
(五)マルウェアに感染した個人所有PCが社内ネットワークにVPN接続され,マルウェアが社内ネットワークに拡散するリスク

ア (-),(二)
イ (-),(三)
ウ (-),(四)
エ (-),(五)
オ (二),(三)
カ (二),(四)
キ (二),(五)
ク (三),(四)
ケ (三),(五)
コ (四),(五)

解説を開く

正解はエ(-),(五)です。

(-)VPN接続が増加し,可用性が損なわれるリスク
(五)マルウェアに感染した個人所有PCが社内ネットワークにVPN接続され,マルウェアが社内ネットワークに拡散するリスク

選ぶのは客先常駐開発部員に,個人所有PCからのVPN接続を許可した場合に,増加する又は新たに生じると考えられるリスクです。

(二)はA社PC、(四)総務部員である点から、関係ありません。
(三)は、VPN接続とは関連が薄いです。

R4問19

問19 A社は従業員200名の通信販売業者である。一般消費者向けに生活雑貨,ギフト商品などの販売を手掛けている。取扱商品の一つである商品Zは,Z販売課が担当している。

[Z販売課の業務]
現在,Z販売課の要員は,商品Zについての受注管理業務及び問合せ対応業務を行っている。商品Zについての受注管理業務の手順を図1に示す。

商品Zの顧客からの注文は電子メールで届く。
(1)入力
 販売担当者は,届いた注文(変更,キャンセルを含む)の内容を受注管理システム1)(以下,Jシステムという)に入力し,販売責任者2)に承認を依頼する。
(2)承認
 販売責任者は,注文の内容とJシステムへの入力結果を突き合せて確認し,問題がなければ承認する。問題があれば差し戻す。

注1)A社情報システム部が運用している。利用者は,販売責任者,販売担当者などである。
注2)Z販売課の課長1名だけである。

図1 受注管理業務の手順

[Jシステムの操作権限]
Z販売課では,Jシステムについて,次の利用方針を定めている。
[方針1]ある利用者が入力した情報は,別の利用者が承認する。
[方針2]販売責任者は,Z販売課の全業務の情報を閲覧できる。

Jシステムでは,業務上必要な操作権限を利用者に与える機能が実装されている。
この度,商品Zの受注管理業務が受注増によって増えていることから,B社に一部を委託することにした(以下,商品Zの受注管理業務の入力作業を行うB社従業員を商品ZのB社販売担当者といい,商品ZのB社販売担当者の入力結果を閲覧して,不備があればA社に口頭で差戻しを依頼するB社従業員を商品ZのB社販売責任者という)。

委託に当たって,Z販売課は情報システム部にJシステムに関する次の要求事項を伝えた。

[要求1]B社が入力した場合は,A社が承認する。
[要求2]A社の販売担当者が入力した場合は,現状どおりにA社の販売責任者が承認する。

上記を踏まえ,情報システム部は今後の各利用者に付与される操作権限を表1にまとめ,Z販売課の情報セキュリティリーダーであるCさんに確認をしてもらった。

表1 操作権限案

利用者 付与される操作権限 Jシステム
閲覧 入力 承認
(省略)
Z販売課の販売担当者 (省略) (省略) (省略)
a1
a2

注記 ○は,操作権限が付与されることを示す。

設問 表1中の a1,a2 に入れる字句の適切な組合せを,aに関する解答群の中から選べ。

aに関する解答群

a1 a2
Z販売課の販売責任者 商品ZのB社販売責任者
Z販売課の販売責任者 商品ZのB社販売担当者
商品ZのB社販売責任者 Z販売課の販売責任者
商品ZのB社販売責任者 商品ZのB社販売担当者
商品ZのB社販売担当者 商品ZのB社販売責任者
解説を開く

正解はエ(商品ZのB社販売責任者商品ZのB社販売担当者)です。

選択肢も使って絞ると、効率的です。

まずa1について、閲覧のみ行えるのは、以下の3人のうち誰か、を考えます。
Z販売課の販売責任者、商品ZのB社販売責任者、商品ZのB社販売担当者

販売課の販売責任者は、承認が、B社販売担当者は、入力ができる必要があります。
そのため、消去法で、a1は商品ZのB社販売責任者と分かります。

この時点で、ウかエに絞られます。

a2について、閲覧と入力ができるのは以下の2人のどちらか、を考えます。
Z販売課の販売責任者、商品ZのB社販売担当者

Z販売課の販売責任者は、承認ができる必要があります。
そのため、消去法で、a2は商品ZのB社販売担当者と分かります。

R4問20

問20 A社は栄養補助食品を扱う従業員500名の企業である。A社のサーバ及びファイアウォール(以下,FWという)を含む情報システムの運用は情報システム部が担当している。

ある日,内部監査部の監査があり,FWの運用状況について情報システム部のB部長が図1のとおり説明したところ,表1に示す指摘を受けた。

・FWを含め,情報システムの運用は,情報システム部の運用チームに所属する6名の運用担当者が担当している。
・FWの運用には,FWルールの編集,操作ログの確認,並びに編集後のFWルールの確認及び操作の承認(以下,編集後のFWルールの確認及び操作の承認を操作承認という)の三つがある。
・FWルールの編集は事前に作成された操作指示書に従って行う。
・FWの機能には,FWルールの編集,操作ログの確認,及び操作承認の三つがある。
・FWルールの変更には,FWルールの編集と操作承認の両方が必要である。操作承認の前に操作ログの確認を行う。
・FWの利用者IDは各運用担当者に個別に発行されており,利用者IDの共用はしていない。
・FWでは,機能を利用する権限を運用担当者の利用者IDごとに付与できる。
・現在は,6名の運用担当者とも全権限を付与されており,運用担当者はFWのルールの編集後,編集を行った運用担当者が操作に誤りがないことを確認し,操作承認をしている。
・FWへのログインにはパスワードを利用している。パスワードは8文字の英数字である。
・FWの運用では,運用担当者の利用者IDごとに,ネットワークを経由せずコンソールでログインできるかどうか,ネットワークを経由してリモートからログインできるかどうかを設定できる。
・FWは,ネットワークを経由せずコンソールでログインした場合でも,ネットワークを経由してリモートからログインした場合でも,同一の機能を利用できる。
・FWはサーバルームに設置されており,サーバルームにはほかに数種類のサーバも設置されている。
・運用担当者だけがサーバルームへの入退室を許可されている。

図1 FWの運用状況

表1 内部監査部からの指摘

指摘1 FWの運用の作業の中で,職務が適切に分離されていない。
指摘2 (省略)
指摘3 (省略)
指摘4 (省略)

B部長は表1の指摘に対する改善策を検討することにした。

設問 表1中の指摘1について,FWルールの誤った変更を防ぐための改善策はどれか。解答群のうち,最も適切なものを選べ。

解答群
ア Endpoint Detection and Response(EDR)をコンソールに導入し,監視を強化する。
イ FWでの運用担当者のログインにはパスワード認証の代わりに多要素認証を導入する。
ウ FWのアクセス制御機能を使って,運用担当者をコンソールからログインできる者,リモートからログインできる者に分ける。
エ FWの運用担当者を1人に限定する。
オ 運用担当者の一部を操作ログの確認だけをする者とし,それらの者には操作ログの確認権限だけを付与する。
カ 運用担当者を,FWルールの編集を行う者,操作ログを確認し,操作承認をする者に分け,それぞれに必要最小限の権限を付与する。
キ 作業を行う運用担当者を,曜日ごとに割り当てる。

解説を開く

正解はカです。

指摘1FWの運用の作業の中で,職務が適切に分離されていない。
の改善案は、職務を適切に分離することだと推測できます。

該当する選択肢は、ウ、エ、カに絞られます。
・・・続く

さらに、問題文を読むと
`

令和5年度

R5問1(素数)

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

:::

関数 findPrimeNumbers は,引数で与えられた整数以下の,全ての素数だけを格納した配列を返す関数である。ここで,引数に与える整数は 2 以上である。


〔プログラム〕

○整数型の配列:findPrimeNumbers(整数型:maxNum)
  整数型の配列:pnList ← {}  // 要素数0の配列
  整数型:i,j
  論理型:divideFlag

  for(i を 2 から 【 a 】まで 1 ずつ増やす)
    divideFlag ← true

    /* i の正の平方根の整数部分が 2 未満のときは,繰返し処理を実行しない */
    for(j を 2 から i の正の平方根の整数部分 まで 1 ずつ増やす)  // α
      if(【 b 】)
        divideFlag ← false
        α の行から始まる繰返し処理を終了する
      endif
    endfor

    if(divideFlag が true と等しい)
      pnList の末尾 に i の値 を追加する
    endif
  endfor

  return pnList

解答群

a b
maxNum i ÷ j の余り が 0 と等しい
maxNum i ÷ j の商 が 1 と等しくない
maxNum + 1 i ÷ j の余り が 0 と等しい
maxNum + 1 i ÷ j の商 が 1 と等しくない

✓R5問2(関数)

次の記述中の【   】に入れる正しい答えを、解答群の中から選べ。

次のプログラムにおいて、手続 proc2 を呼び出すと、【   】の順に出力される。

〔プログラム〕

○ proc1()
  "A" を出力する
  proc3()

○ proc2()
  proc3()
  "B" を出力する
  proc1()

○ proc3()
  "C" を出力する

解答群

ア ”A”, “B”, “B”, “C”
イ ”A”, “C”
ウ ”A”, “C”, “B”, “C”
エ ”B”, “A”, “B”, “C”
オ ”B”, “C”, “B”, “A”
カ ”C”, “B”
キ ”C”, “B”, “A”
ク ”C”, “B”, “A”, “C”

解説を開く

正解はク “C”, “B”, “A”, “C” です。

呼び出すproc2から、proc1とproc3も呼び出します。
マウスポインタだけでは処理を追えないため、proc2を書き出して、消し込みながらトレースしましょう。

トレース表に書く例

p3()
“B”
p1()

proc3、proc1はポインタでトレースすればOKです。

①1行目
proc3()を実行します。

出力結果

C

実行済みなので、取り消し線を引きます。

p3()
“B”
p1()

②2行目

出力結果

C B
p3()
“B”
p1()

③3行目

出力結果

C B A C
p3()
“B”
p1()

よって正解はク “C”, “B”, “A”, “C” です。

✓R5問3(while)

次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる。

次の手続 sort は,大域の整数型の配列 data の,引数 first で与えられた要素番号から引数 last で与えられた要素番号までの要素を昇順に整列する。ここで,first < last とする。

手続 sort を sort(1, 5) として呼び出すと,/ α / の行を最初に実行したときの出力は「【 】」 となる。

大域: 整数型の配列: data ← {2, 1, 3, 5, 4}
○ sort(整数型: first, 整数型: last)
    整数型: pivot, i, j
    pivot ← data[(first + last) ÷ 2 の商]
    i ← first
    j ← last

    while (true)
        while (data[i] < pivot)
            i ← i + 1
        endwhile
        while (pivot < data[j])
            j ← j − 1
        endwhile
        if (i ≥ j)
            繰返し処理を終了する
        endif
        data[i] と data[j] の値を入れ替える
        i ← i + 1
        j ← j − 1
    endwhile
    data の全要素の値を要素番号の順に空白区切りで出力する   /*** α ***/
    if (first < i − 1)
        sort(first, i − 1)
    endif
    if (j + 1 < last)
        sort(j + 1, last)
    endif

解答群
ア 1 2 3 4 5
イ 1 2 3 5 4
ウ 2 1 3 4 5
エ 2 1 3 5 4

解説を開く

①トレース表を作成
Data

1 2 3 4 5
2 1 3 5 4

トレース表

pivot i j while(data[i] < 3) while(3<data[j]) if(i≧j)
data[(1+5)/2]
data[3]
3
1 5

以下3行を反映済みです。
`pivot ← data[(first + last) ÷ 2 の商]`
`i ← first`
`j ← last`

②`while (true)`
条件判定不要で、常に繰り返します。

`繰返し処理を終了する`が実行された時に、終了します。

③ `while (data[i] < pivot)`

| pivot | i | j |while(data[i] < 3)|while(3 2   
**○** | | |
| | 3 | | ~~data[2]~~<3
1   
**○** | | |
| | | | ~~data[3]~~<3
3   
**×** | | |

⑤`while (pivot < data[j])`

| pivot | i | j |while(data[i] < 3)|while(3 4   
**○** | |
| | | **3** | | 3< ~~data[4]~~
5   
**○** | |
| | | | | 3< ~~data[3]~~
3   
**×** ||

⑦`if (i ≥ j)`

| pivot | i | j | while(data[i] < 3) | while(3**○** |

`繰り返し処理を終了する`

⑩`data の全要素の値を要素番号の順に空白区切りで出力する`

data

| 1 | 2 | 3 | 4 | 5 |
|:—:|:—:|:—:|:—:|:—:|
| 2 | 1 | 3 | 5 | 4 |

なので出力は「2 1 3 5 4」(ア)

>**Memo:効率的なトレース**
>
>iは1から1ずつ増え、jは5から1ずつ減るので、dataの配列表上で以下のように判定できます。
>
>Data
>
>| | 1 | 2 | 3 | 4 | 5 |
>| :——-: | :-: | :-: | :-: | :-: | :-: |
>| | 2 | 1 | 3 | 5 | 4 |
>| data[i]<3 | ○ | ○ | × | | |
>| 3
>i,j共に3になるとわかれば、あとは`if (i ≥ j)`を判定すればOKです。

✓R5問4(ハッシュ)

次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる

関数 add は,引数で指定された正の整数 value を大域の整数型の配列 hashArray に格納する。
格納できた場合は true を返し,格納できなかった場合は false を返す。

ここで,整数 value を hashArray のどの要素に格納すべきかを,関数 calcHash1 及び calcHash2 を利用して決める。

手続 test は,関数 add を呼び出して,hashArray に正の整数を格納する。
手続 test の処理が終了した直後の hashArray の内容は,【 】である。

〔プログラム〕

大域: 整数型の配列: hashArray
○ 論理型: add(整数型: value)
    整数型: i ← calcHash1(value)

    if (hashArray[i] = -1)
        hashArray[i] ← value
        return true
    else
        i ← calcHash2(value)
        if (hashArray[i] = -1)
            hashArray[i] ← value
            return true
        endif
    endif

    return false

○ 整数型: calcHash1(整数型: value)
    return (value mod hashArray の要素数) + 1

○ 整数型: calcHash2(整数型: value)
    return ((value + 3) mod hashArray の要素数) + 1

○ test()
    hashArray ← {5個の -1}

    add(3)
    add(18)
    add(11)

解答群
ア {−1, 3, −1, 18, 11}
イ {−1, 11, −1, 3, −1}
ウ {−1, 11, −1, 18, −1}
エ {−1, 18, −1, 3, 11}
オ {−1, 18, 11, 3, −1}

ヒント:modは、余りを求める演算子です。
例:
3 mod 10 = 3
10 mod 3 = 1

解説を開く

正解はエ {−1, 18, −1, 3, 11} です。

①トレース表の作成

i value if(hashArray[i] = -1)

hashArray

1 2 3 4 5
-1 -1 -1 -1 -1

add(3)のトレース

i value if(hashArray[i] = -1)
3

i ← calcHash1(value)

calcHash1の処理は`return (value mod hashArray の要素数) + 1`の1行なので、計算式をiに直接トレースしてしまいます。

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3

if (hashArray[i] = -1)の判定

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3 hashArray[4] = -1
-1

hashArray[i] ← value

hashArray

1 2 3 4 5
-1 -1 -1 -1 -1
3

(return true)

⑥(add(18)のトレース)
i ← calcHash1(value)
if (hashArray[i] = -1)の判定

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3 hashArray[4] = -1
-1
—- —- —-
(18 mod 5 )+ 1
4
18 hashArray[4] = -1
3
×

⑦×なので、elseの処理に進みます。
i ← calcHash2(value)

(calcHash2)return ((value + 3) mod hashArray の要素数) + 1

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3 hashArray[4] = -1
-1
—- —- —-
(18 mod 5 )+ 1
4
18 hashArray[4] = -1
3
×
((18 + 3) mod 5 )+ 1
2


if (hashArray[i] = -1)の判定

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3 hashArray[4] = -1
-1
—- —- —-
(18 mod 5 )+ 1
4
18 hashArray[4] = -1
3
×
((18 + 3) mod 5 )+ 1
2
hashArray[2] = -1
-1

hashArray[i] ← value

hashArray

1 2 3 4 5
-1 -1 -1 -1 -1
18 3

add(11)のトレース

i value if(hashArray[i] = -1)
(3 mod 5 )+ 1
4
3 hashArray[4] = -1
-1
—- —- —-
(18 mod 5 )+ 1
4
18 hashArray[4] = -1
3
×
((18 + 3) mod 5 )+ 1
2
hashArray[2] = -1
-1
—- —- —-
(11 mod 5 )+ 1
2
11 hashArray[2] = -1
18
×
((11 + 3) mod 5 )+ 1
5
hashArray[5] = -1
-1

hashArray[i] ← value

hashArray

1 2 3 4 5
-1 -1 -1 -1 -1
18 3 11

よって正解はエ {−1, 18, −1, 3, 11} です。

✓R5問5(コサイン類似度)

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

コサイン類似度は,二つのベクトルの向きの類似性を測る尺度である。
関数 calcCosineSimilarity は,いずれも要素数が n(n≧1)である実数型の配列 vector1vector2 を受け取り,二つの配列のコサイン類似度を返す。
配列 vector1 が {a₁, a₂, …, aₙ},配列 vector2 が {b₁, b₂, …, bₙ} のとき,コサイン類似度は次の数式で計算される。
ここで,配列 vector1 と配列 vector2 のいずれも,全ての要素に 0 が格納されていることはないものとする。

$$
\frac{\mathrm{a}_{1}\mathrm{b}_{1}+\mathrm{a}_{2}\mathrm{b}_{2}+\cdots+\mathrm{a}_{n}\mathrm{b}_{n}}{\sqrt{\mathrm{a}_{1}^{2}+\mathrm{a}_{2}^{2}+\cdots+\mathrm{a}_{n}^{2}}\sqrt{\mathrm{b}_{1}^{2}+\mathrm{b}_{2}^{2}+\cdots+\mathrm{b}_{n}^{2}}}
$$

〔プログラム〕

○ 実数型: calcCosineSimilarity(実数型の配列: vector1,
                              実数型の配列: vector2)
  実数型: similarity, numerator, denominator, temp ← 0
  整数型: i
  numerator ← 0

  for (i を 1 から vector1の要素数 まで 1 ずつ増やす)
    numerator ← numerator + 【 a 】
  endfor

  for (i を 1 から vector1の要素数 まで 1 ずつ増やす)
    temp ← temp + vector1[i] の2乗
  endfor
  denominator ← temp の正の平方根

  temp ← 0
  for (i を 1 から vector2の要素数 まで 1 ずつ増やす)
    temp ← temp + vector2[i] の2乗
  endfor
  denominator ← 【 b 】

  similarity ← numerator ÷ denominator
  return similarity

a b
(vector1[i] × vector2[i]) の正の平方根 denominator × (tempの正の平方根)
(vector1[i] × vector2[i]) の正の平方根 denominator + (tempの正の平方根)
(vector1[i] × vector2[i]) の正の平方根 tempの正の平方根
vector1[i] × vector2[i] denominator × (tempの正の平方根)
vector1[i] × vector2[i] denominator + (tempの正の平方根)
vector1[i] × vector2[i] tempの正の平方根
vector1[i] の2乗 denominator × (tempの正の平方根)
vector1[i] の2乗 denominator + (tempの正の平方根)
vector1[i] の2乗 tempの正の平方根
解説を開く

①式と戻り値を確認
コサイン類似度を求める式が書かれており、二つの配列のコサイン類似度を返すより、式がそのまま戻り値となることも確認しておきます。

②解答群を確認

以下が読み取れます。

  • aは3択(vector1[i] × vector2[i] | vector1[i] の2乗 | vector1[i])
  • bも3択(denominator × (tempの正の平方根) | denominator + (tempの正の平方根) | tempの正の平方根)
aの候補 bの候補
vector1[i] × vector2[i] denominator × (tempの正の平方根)
vector1[i] の2乗 denominator + (tempの正の平方根)
vector1[i] tempの正の平方根

候補をトレース表に書いておくと、解きやすいです。書く際は、v1[i]、deno、などわかる形で省略しましょう。

③問われている内容を確認
numerator ← numerator + 【 a 】
denominator ← 【 b 】
なので、numeratorとdenominatorが何を指すのかを確認します。

similarity ← numerator ÷ denominatorのあと、similarityをreturnしています。

よって、①で確認した式は、プログラム上numerator ÷ denominatorです。

$$
\frac{numerator}{denominator}
$$

(問題文の式)

$$
\frac{\mathrm{a}_{1}\mathrm{b}_{1}+\mathrm{a}_{2}\mathrm{b}_{2}+\cdots+\mathrm{a}_{n}\mathrm{b}_{n}}{\sqrt{\mathrm{a}_{1}^{2}+\mathrm{a}_{2}^{2}+\cdots+\mathrm{a}_{n}^{2}}\sqrt{\mathrm{b}_{1}^{2}+\mathrm{b}_{2}^{2}+\cdots+\mathrm{b}_{n}^{2}}}
$$

`配列 vector1 が {a₁, a₂, …, aₙ},配列 vector2 が {b₁, b₂, …, bₙ} のとき`とあるので、aがvector1、bがvector2であることもこのタイミングで確認しておけるとスムーズです。

numerator ← numerator + 【 a 】

numeratorが使われているのは、以下の1箇所のみです。

  for (i を 1 から vector1の要素数 まで 1 ずつ増やす)
    numerator ← numerator + 【 a 】
  endfor

式より、numeratorの完成形はa₁b₁+a₂b₂+...+aₙbₙです。

aの候補は以下の3択なので、この中でどれを入れれば、完成形になるかを考えます。

aの候補
vector1[i] × vector2[i]
vector1[i] の2乗
vector1[i]

問題文配列 vector1 が {a₁, a₂, …, aₙ},配列 vector2 が {b₁, b₂, …, bₙ} のときより、vector1はa、vector2はbです。
vector2(b)が使われているのはvector1[i] × vector2[i])だけなので、【a】はvector1[i]✕vector2[i]です。

denominator ← 【 b 】

denominatorの完成形の式は√(a₁²+a₂²+...+aₙ²) √(b₁²+b₂²+...+bₙ²)(式の分母)です。
denominatorはプログラム上、以下の2箇所で代入されています。

  for (i を 1 から vector1の要素数 まで 1 ずつ増やす)
    temp ← temp + vector1[i] の2乗
  endfor
  denominator ← temp の正の平方根
  temp ← 0
  for (i を 1 から vector2の要素数 まで 1 ずつ増やす)
    temp ← temp + vector2[i] の2乗
  endfor
  denominator ← 【 b 】

実際には2つの処理は連続しています。わかりやすいようにブロックを分けています。

1つめの繰り返しでvector1(a)が、2つめの繰り返しがvector2(b)が使われています。
よって1回目の繰り返しのdenominator ← temp の正の平方根によって完成形の√(a₁²+a₂²+...+aₙ²) √(b₁²+b₂²+...+bₙ²)のうち、前半のa₁部分√(a₁²+a₂²+...+aₙ²)が代入されていると推測できます。

なお、ここで`正の平方根`が√を指すこともわかります。

√(a₁²+a₂²+…+aₙ²)が代入されているdenominatorを完成形の√(a₁²+a₂²+...+aₙ²) √(b₁²+b₂²+...+bₙ²)とするには、dominatorに√(b₁²+b₂²+...+bₙ²)かけ合わせれば良いです。
選択肢の中でdominator ✕があるのは1択なので、【b】にはdenominator × (tempの正の平方根)が入ります。

ゼロから解答しようとすると、tempの中身が`b₁²+b₂²+…+bₙ²`であることも確認する必要がありますが、解答群を検討すれば`denominator × (tempの正の平方根)`一択だとわかります。

R5問6(情報セキュリティ)

問6 A社は,放送会社や運輸会社向けに広告制作ビジネスを展開している。A社は,人事業務の効率化を図るべく,人事業務の委託を検討することにした。A社が委託する業務(以下,B業務という)を図1に示す。

・採用予定者から郵送されてくる入社時の誓約書,前職の源泉徴収票などの書類をPDFファイルに変換し,ファイルサーバに格納する。
(省略)

図1 B業務

委託先候補のC社は,B業務について,次のようにA社に提案した。

・B業務だけに従事する専任の従業員を割り当てる。
・B業務では,図2の複合機のスキャン機能を使用する。

・スキャン機能を使用する際は,従業員ごとに付与した利用者IDとパスワードをパネルに入力する。
・スキャンしたデータをPDFファイルに変換する。
・PDFファイルを従業員ごとに異なる鍵で暗号化して,電子メールに添付する。
・スキャンを実行した本人宛てに電子メールを送信する。
・PDFファイルが大きい場合は,PDFファイルを添付する代わりに,自社の社内ネットワーク上に設置したサーバ(以下,Bサーバという)1)に自動的に保存し,保存先のURLを電子メールの本文に記載して送信する。

注1)Bサーバにアクセスする際は,従業員ごとの利用者IDとパスワードが必要になる。

図2 複合機のスキャン機能(抜粋)

A社は,C社と業務委託契約を締結する前に,秘密保持契約を締結した。その後,C社に質問表を送付し,回答を受けて,業務委託での情報セキュリティリスクの評価を実施した。その結果,図3の発見があった。

・複合機のスキャン機能では,電子メールの差出人アドレス,件名,本文及び添付ファイル名を初期設定1)の状態で使用しており,誰がスキャンを実行しても同じである。
・複合機のスキャン機能の初期設定情報はベンダーのWebサイトで公開されており,誰でも閲覧できる。

注1)複合機の初期設定はC社の情報システム部だけが変更可能である。

図3 発見事項

そこで,A社では,初期設定の状態のままではA社にとって情報セキュリティリスクがあり,初期設定から変更するという対策が必要であると評価した。

設問 対策が必要であるとA社が評価した情報セキュリティリスクはどれか。解答群のうち,最も適切なものを選べ。

解答群
ア B業務に従事する従業員が,攻撃者からの電子メールを複合機からのものと信じて本文中にあるURLをクリックし,フィッシングサイトに誘導される。その結果,A社の採用予定者の個人情報が漏えいする。
イ B業務に従事する従業員が,複合機から送信される電子メールをスパムメールと誤認し,電子メールを削除する。その結果,再スキャンが必要となり,B業務が遅延する。
ウ 攻撃者が,複合機から送信される電子メールを盗聴し,添付ファイルを暗号化して身代金を要求する。その結果,A社が復号鍵を受け取るために多額の身代金を支払うことになる。
エ 攻撃者が,複合機から送信される電子メールを盗聴し,本文に記載されているURLを使ってBサーバにアクセスする。その結果,A社の採用予定者の個人情報が漏えいする。

解説を開く

正解はアです。
「図3の発見によって,攻撃者が何をできるようになるか」を攻撃者の視点で考えると解きやすいです。
図3では,複合機のスキャン機能の初期設定情報(電子メールの差出人アドレス,件名,本文及び添付ファイル名)が公開されており,誰でも同じ体裁のメールを作成できる可能性があります。
このため,攻撃者が複合機から送信されたかのようなメールを偽装し,本文中のURLをクリックさせてフィッシングサイトへ誘導するリスクが考えられます。

一方,ウやエは「盗聴」を前提としていますが,図3の発見事項からは通信を盗聴できるとは読み取れません。

令和6年度

✓R6問1(分岐)

次のプログラムの空欄【】に入れる正しい答えを、解答群から選べ。

関数maximumは異なる3つの整数を引数で受け取り、そのうちの最大値を返す。

○ 整数型: maximum(整数型: x, 整数型: y, 整数型: z)
if ( 【  】 )
  return y
elseif (x > z)
  return x
else
  return z
endif

解答群
ア x > y
イ y > x and y > z
ウ z > y
エ x > y and x > z
オ y > x and z > y
カ z > x and z > y

解説を開く

正解 イ

最大値としてyを返しているので、【  】内に入る条件は「yが最大値の場合」だとわかります。

引数はx,y,zの3つなので「yが最大値の場合」とは、「yがxよりも大きくて、zよりも大きい場合」です。
これを式として表しているのはイy > x and y > z(イ)です。

Memo:elseif以降の補足
条件分岐は、前の条件を満たさなかった場合のみ、次の条件判定を行います。
2回目の分岐となるelseif()が実行されるのは、「yが最大値ではない場合」です。

text
if (yが最大値の場合)
return y
elseif (x > z) //yが最大値でない場合
return x
else //yが最大値でないかつ、xが最大値でない場合
return z
endif

yが最大値でないということは、最大値はxかzのどちらかです。
そのため、xとzの両者を比較して大きい方が、最大値です。

さらに、最後のelseは、「yが最大値でない」し「xが最大値でない」場合にのみ到達します。
つまり、最大値はzです。

✓R6問2(2進数)

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

関数 convDecimal は,引数として与えられた,“0” と “1” だけから成る,1文字以上の文字列を,符号なしの2進数と解釈したときの整数値を返す。例えば,引数として “10010” を与えると 18 が返る。
関数 convDecimal が利用する関数 int は,引数で与えられた文字が “0” なら整数値 0 を返し,“1” なら整数値 1 を返す。

○ 整数型: convDecimal(文字列型: binary)
    整数型: i, length, result ← 0
    length ← binary の文字数
    for (i を 1 から length まで 1 ずつ増やす)
        result ← 【 】
    endfor
    return result

解答群

ア result + int(binary の (length − i + 1)文字目の文字)
イ result + int(binary の i文字目の文字)
ウ result × 2 + int(binary の (length − i + 1)文字目の文字)
エ result × 2 + int(binary の i文字目の文字)

解説を開く

正解はエです。

①問題文より、関数convDecimalは引数の文字列を2進数として10進数に変換する関数です。

プログラムの穴埋め問題の場合、問題文の説明と一致するように解答を選びます。そのため、必ず問題文を理解してから解きましょう。 逆に、トレース系の場合は、「ヒントになるかも」程度なので、理解できなければトレースしてしまってOKです。

②解答群を整理すると、問われているのは以下の2点です。

  • resultを✕2するか、しないか
  • resultに足すのはbinary の i文字目からか、(length − i + 1)文字目からか

ここで、i文字目が何を指すかも確認します。
まず、iは1からとあるので、1周目の時に1文字目を指します。
ゃぱそん”の1文字目が”じ”であるように、”10010″の1文字目は左端の”1″です。

さらに、lengthは5なので、length-i+1は、1周目の時5です。

つまり、

  • resultに足すのは”10010″の左の”1″からか、右の”0″からか

です。

まとめると

  • resultを✕2するか、しないか
  • resultに足すのは”10010″の左の”1″からか、右の”0″からか

この2つがわかれば、正解がわかります。

③問われている内容

for文の中で、resultに代入する中身が問われています。プログラム上、他の処理は行われていないため、【】の中身だけで、”10010″が18に変換される必要があります。

ここで、2進数を10進数する変換のおさらいです。
10010を10進数に変換するには、以下のように1になっている桁の重みを足し合わせます。

*16 *8 *4 *2 *1
1 0 0 1 0
(✕2を4回) (✕2を1回)

ここで、重みは、桁が1つ増えるごとに✕2を繰り返した値です。
左の1が、最も多く✕2を繰り返す必要があります。

よって、正解はエresult × 2 + int(binary の i文字目の文字)です。

具体的には1文字目の1(**1**0010)は、16を表すため、✕2を4回行う必要があります。一方で5文字目の0は、1を表すため、✕2は不要(0回)です。

(参考:トレースした場合)

| i(1~5) | result|
| :—: | :—: |
| 1 | 0✕2+1
1|
| 2 | 1✕2+0
2|
| 3 | 2✕2+0
4|
| 4 | 4✕2+1
9|
| 5 | 9✕2+0
18|

Memo:n-i+1length-i+1

これまでにも何度か登場したn-i+1(nは要素数)や、length-i+1(lengthは文字列の長さ)は、後ろからi番目を指します。
n(length)が5で、iを1からnまで1ずつ増やすの場合、n-i+1は5から始まって4,3,2,1と減っていきます。
iと対になる回答候補として登場しやすいので、覚えておくと時短に繋がります。
(トレースすればすぐわかるので、必須ではありません)

✓R6問3(隣接行列)

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

図1に示すグラフの頂点には,1から順に整数で番号が付けられている。グラフは無向グラフであり,各頂点間には高々一つの辺がある。一つの辺は両端の頂点の番号を要素にもつ要素数2の整数型の配列で表現できる。例えば,{1,3}は頂点1と頂点3を端点とする辺を表す。グラフ全体は,グラフに含まれる辺を表す要素数2の配列を全て格納した配列(以下,辺の配列という)で表現できる。辺の配列の要素数はグラフの辺の個数と等しい。図1のグラフは整数型配列の配列{{1,3},{1,4},{3,4},{2,4},{4,5}}と表現できる。

image-20260109105815091

図1 グラフの例

関数 edgesToMatrix は,辺の配列を隣接行列に変換する。隣接行列とは,グラフに含まれる頂点の個数と等しい行数及び列数の正方行列で,i行j列の成分は頂点iと頂点jを結ぶ辺があるときに1となり,それ以外は0となる。行列の対角成分は全て0で,無向グラフの場合は対称行列になる。図1のグラフを表現する隣接行列を図2に示す。

image-20260109105826786
図2 図1のグラフを表現する隣接行列

関数 edgesToMatrix は,引数 edgeList で辺の配列を,引数 nodeNum でグラフの頂点の個数をそれぞれ受け取り,隣接行列を表す整数型の二次元配列を返す。


〔プログラム〕

○整数型の二次元配列:edgesToMatrix(整数型配列の配列:edgeList,
                             整数型:nodeNum)
  整数型の二次元配列:adjMatrix ← {nodeNum行nodeNum列の0}
  整数型:i,u,v

  for (i を 1 から edgeListの要素数 まで 1 ずつ増やす)
    u ← edgeList[i][1]
    v ← edgeList[i][2]

    【   】
  endfor

  return adjMatrix

解答群

ア adjMatrix[u, u] ← 1
イ adjMatrix[u, u] ← 1
  adjMatrix[v, v] ← 1
ウ adjMatrix[u, v] ← 1
エ adjMatrix[u, v] ← 1
  adjMatrix[v, u] ← 1
オ adjMatrix[v, u] ← 1
カ adjMatrix[v, v] ← 1

✓R6問4

次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。
ここで,配列の要素番号は 1 から始まる。

関数 merge は,昇順に整列された整数型の配列 data1及び data2を受け取り,これらを併合してできる昇順に整列された整数型の配列を返す。
関数 merge をmerge({2, 3}, {1, 4})として呼び出すと,αの行は 【  】

〔プログラム〕

○ 整数型の配列: merge(整数型の配列: data1, 整数型の配列: data2)
    整数型: n1 ← data1 の要素数
    整数型: n2 ← data2 の要素数
    整数型の配列: work ← { (n1 + n2) 個の未定義の値 }
    整数型: i ← 1
    整数型: j ← 1
    整数型: k ← 1

    while ((i ≤ n1) and (j ≤ n2))
        if (data1[i] ≤ data2[j])
            work[k] ← data1[i]
            i ← i + 1
        else
            work[k] ← data2[j]
            j ← j + 1
        endif
            k ← k + 1
    endwhile

    while (i ≤ n1)
        work[k] ← data1[i]
        i ← i + 1
        k ← k + 1
    endwhile

    while (j ≤ n2)
        work[k] ← data2[j]  /***α***/
        j ← j + 1
        k ← k + 1
    endwhile

    return work

解答群
ア 実行されない  イ 1回実行される
ウ 2回実行される エ 3回実行される

ヒント:`while ((i ≤ n1) and (j ≤ n2))`は、両方がTrueのときにTrueとなります。

解説を開く

正解は エ {1, 2, 3, 4} です。

①トレース表を作成
data1

1 2
2 3

data2

1 2
1 4

work

1 2 3 4

(`整数型の配列: work ← { (n1 + n2) 個の未定義の値 }`を反映)

トレース表

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1

整数型: n1 ← data1 の要素数
整数型: n2 ← data2 の要素数
整数型: i ← 1
整数型: j ← 1
整数型: k ← 1
を反映

while ((i ≤ n1) and (j ≤ n2)) 1周目

n1 n2 i j k while((i ≤ n1) and (j ≤ n2)) if(data1[i] ≤ data2[j]) while(i<n1) while(j<n2)
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 (1≤2) and (1≤2)
data1[1]≤data2[1]
2≤1
×
—- —- —- —- —- —- —- —- —-
2 3
—- —- —- —- —- —- —- —- —-
3 4
—- —- —- —- —- —- —- —- —-
(3≦2) and (2≤2)
×

④falseなのでelseの処理を行う
work[k] ← data2[j]

work

1 2 3 4
data2[j]
data2[1]
1

以下の2ステップで反映しましょう。
1.work[k]を処理する
kは1です。配列表のwork[1]に、`data2[j]`を記入します。

2.data2[j]の値を読み取る
jは1です。data2[1]の値を、work[1]に上書きします。

j ← j + 1

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 (1≤2) and (1≤2)
t
data1[1]≤data2[1]
2≤1
f

k ← k + 1

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 (1≤2) and (1≤2)
t
data1[1]≤data2[1]
2≤1
f

⑦(2周目)
(i ≤ n1) and (j ≤ n2)を判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
(1≦2) and (2≤2)
t

if (data1[i] ≤ data2[j])を判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
(1≦2) and (2≤2)
t
data1[1]≤data2[2]
2≤4
t

⑧true時の処理、および分岐後の処理を行う
work[k] ← data1[i]

work

1 2 3 4
data2[j]
data2[1]
1
data1[i]
data1[1]
2

i ← i + 1
k ← k + 1

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
2 3 (1≦2) and (2≤2)
t
data1[1]≤data2[2]
2≤4
t

⑨(3周目)
(i ≤ n1) and (j ≤ n2)を判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
2 3 t t
—- —- —- —- —- —- —- —- —-
(2≦2) and (2≤2)
t

⑩if(data1[i] ≤ data2[j])を判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
2 3 t t
—- —- —- —- —- —- —- —- —-
(2≦2) and (2≤2)
t
data1[2]≤data2[2]
3≤4
t

⑪true時の処理、および分岐後の処理を行う
work[k] ← data1[i]

work

1 2 3 4
data2[j]
data2[1]
1
data1[i]
data1[1]
2
data1[i]
data1[2]
3

i ← i + 1
k ← k + 1

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
2 3 t t
—- —- —- —- —- —- —- —- —-
3 4 (2≦2) and (2≤2)
t
data1[2]≤data2[2]
3≤4
t

⑫(4周目)
(i ≤ n1) and (j ≤ n2)を判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
2 2 1 1 1
—- —- —- —- —- —- —- —- —-
2 2 t f
—- —- —- —- —- —- —- —- —-
2 3 t t
—- —- —- —- —- —- —- —- —-
3 4 t t
—- —- —- —- —- —- —- —- —-
(3≦2) and (2≤2)
f

(繰り返し終了)

⑬while (i ≤ n1)の判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
2 2 3 2 4
—- —- —- —- —- —- —- —- —-
3<2
f

(1回も行わずに繰り返し終了)

⑭while (j ≤ n2)の判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
2 2 3 2 4
—- —- —- —- —- —- —- —- —-
f
—- —- —- —- —- —- —- —- —-
2<2
t


work[k] ← data2[j]
work

1 2 3 4
data2[j]
data2[1]
1
data1[i]
data1[1]
2
data1[i]
data1[2]
3
data2[j]
data2[2]
4

j ← j + 1
k ← k + 1

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
2 2 3 2 4
—- —- —- —- —- —- —- —- —-
3 5 t

⑯(2周目)while (j ≤ n2)の判定

n1 n2 i j k (i ≤ n1) and (j ≤ n2) data1[i] ≤ data2[j] i<n1 j<n2
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
2 2 3 2 4
—- —- —- —- —- —- —- —- —-
3 5 t
—- —- —- —- —- —- —- —- —-
2<3
f

(繰り返し終了)

αをどうやって数える??

✓R6問5(読解系-商品データ)

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

一度の注文で購入された商品のリストを,注文ごとに記録した注文データがある。
表に,注文データの例を示す。

表 注文データの例

注文番号 購入された商品のリスト
1 A, B, D
2 A, D
3 A
4 A, B, E
5 B
6 C, E

注文データから,商品 x と商品 y とが同一の注文で購入されやすい傾向を示す関連度 Lxy を,次の式で計算する。

$$
L_{xy} = \frac{M_{xy} \times \text{全注文数}}{K_x \times K_y}
$$

ここで,Mxy は商品 x と商品 y とが同一の注文で購入された注文数,Kx は商品 x が購入された注文数,Ky は商品 y が購入された注文数を表す。表の例では,MAB が2,全注文数が6,KA が4,KB が3であるので,商品Aと商品Bの関連度 LAB は,(2 × 6) / (4 × 3) = 1.0 である。

手続 putRelatedItem は,大域変数 orders に格納された注文データを基に,引数で与えられた商品との関連度が最も大きい商品のうちの一つと,その関連度を出力する。プログラムでは,商品は文字列で表し,注文は購入された商品の配列,注文データは注文の配列で表している。注文データには2種類以上の商品が含まれるものとする。また,注文データにある商品以外の商品が,引数として与えられることはないものとする。


〔プログラム〕

// 注文データ(ここでは表の例を与えている)
大域:文字列型配列の配列:orders ← {{"A","B","D"}, {"A","D"}, {"A"},
                                   {"A","B","E"}, {"B"}, {"C","E"}}

○putRelatedItem(文字列型:item)

  文字列型の配列:allItems ← ordersに含まれる文字列を
                            重複なく辞書順に格納した配列
                            // 表の例では {"A","B","C","D","E"}

  文字列型の配列:otherItems ← allItemsの複製から値がitemである
                               要素を除いた配列

  整数型:i,itemCount ← 0
  整数型の配列:arrayK ← {otherItemsの要素数個の0}
  整数型の配列:arrayM ← {otherItemsの要素数個の0}
  実数型:valueL,maxL ← −∞
  文字列型の配列:order
  文字列型:relatedItem

  for (orderにordersの要素を順に代入する)
    if (orderのいずれかの要素の値がitemの値と等しい)
      itemCountの値を1増やす
    endif
    for (iを1からotherItemsの要素数まで1ずつ増やす)
      if (orderのいずれかの要素の値がotherItems[i]の値と等しい)
        if (orderのいずれかの要素の値がitemの値と等しい)
           【 a 】の値を1増やす
        endif
       【 b 】の値を1増やす
      endif
    endfor
  endfor

  for (iを1からotherItemsの要素数まで1ずつ増やす)
    valueL ← (arrayM[i] × 【 c 】) ÷ (itemCount × arrayK[i])
                                            /* 実数として計算する */
    if (valueLがmaxLより大きい)
      maxL ← valueL
      relatedItem ← otherItems[i]
    endif
  endfor

  relatedItemの値とmaxLの値をこの順にコンマ区切りで出力する

解答群

a b c
arrayK[i] arrayM[i] allItemsの要素数
arrayK[i] arrayM[i] ordersの要素数
arrayK[i] arrayM[i] otherItemsの要素数
arrayM[i] arrayK[i] allItemsの要素数
arrayM[i] arrayK[i] ordersの要素数
arrayM[i] arrayK[i] otherItemsの要素数
解説を開く

正解はオ(arrayM[i] | arrayK[i] | ordersの要素数)です。

①式と戻り値を確認

以下、関連度の式です。
$$
L_{xy} = \frac{M_{xy} \times \text{全注文数}}{K_x \times K_y}
$$

引数で与えられた商品との関連度が最も大きい商品のうちの一つと,その関連度を出力する。
とあり、式の結果に対して追加で処理が必要であることを確認しておきます。

②解答群を確認

  • aとbはarrayM[i]かarrayK[i]のどちらか
  • cはallItems/orders/otherItemsいずれかの要素数(3択)

③問われている内容を確認【c】

【a】【b】【c】のうち、解答しやすそうなものから解いていきます。

valueL ← (arrayM[i] × 【 c 】) ÷ (itemCount × arrayK[i])
について、プログラム中の計算式はここだけです。
さらに、その後の処理は、式の結果に対して追加で必要な処理(①より)であると推測できます。

なお、このあとの`if (valueLがmaxLより大きい)`以降の処理は、`関連度が最も大きい商品のうちの一つと,その関連度を出力する`(問題文より)処理です。
このあたりは、時間に余裕がある場合に確認すればOKです。

よって問題文の式がプログラム上ここに該当すると判断できます。

式は、プログラムの後半(戻り値付近、もしくは戻り値そのもの)に、目立つ形で記載されています。
ざっとプログラムを見て「コレだな」と当たりをつけて解いても問題ありません。

(arrayM[i] × 【 c 】) ÷ (itemCount × arrayK[i])を分数で表すと、以下となります。

$$
\frac{arrayM[i] \times \text{【 c 】}}{itemCount \times arrayK[i]}
$$

式に照らし合わせると、【 c 】は全注文数です。
【c】はordersallItemsotherItemsの3択です。

(英語に強い、実務経験がある等により)この中で注文を意味する変数は`orders`だけだと確信できる方は、確定してOKです。

それぞれの変数の説明を調べると、以下がわかります。

変数 説明 記述箇所
orders 大域変数 orders に格納された注文データを基に… 問題文
allItems ordersに含まれる文字列を重複なく辞書順に格納した配列 プログラム内
otherItems allItemsの複製から値がitemである要素を除いた配列 プログラム内

引数に関する説明は、問題文の「関数○○は、~~を引数として××を返す」の部分に記載されています。

「全注文数」と合致するのはordersのみです。よってcはordersの要素数です。

④問われている内容を確認【a】【b】

解答群より、aとbはarrayM[i]かarrayK[i]のどちらかです。
式を照らしあわせると、arrayM[i]はMxy、arrayK[i]はKyです。

(問題文の式)
$$
L_{xy} = \frac{M_{xy} \times \text{全注文数}}{K_x \times K_y}
$$

(プログラム上の式)
$$
\frac{arrayM[i] \times \text{【 c 】}}{itemCount \times arrayK[i]}
$$

MかKかで区別するとわかりやすいです。

⑤Mxy、Kyが何を指すのかを確認

問題文より、Mxyは商品xと商品yとが同一の注文で購入された注文数、Kyは商品yが購入された注文数です。

      if (orderのいずれかの要素の値がotherItems[i]の値と等しい)
        if (orderのいずれかの要素の値がitemの値と等しい)
           【 a 】の値を1増やす
        endif
       【 b 】の値を1増やす
      endif

上記より、【b】よりも【a】の方が増やす際の条件が多いです。

if()内の条件式を、具体的に読み取る必要はありません。「【a】の方が増やす際の条件が多い」とわかれば十分です。

「yが注文されている」よりも「yが注文されていて、xも注文されている」の方が条件が多いので、【a】はarrayM[i] (Mxy)、【b】はarrayK[i] (Ky) です。

よって正解は正解はオ(arrayM[i] | arrayK[i] | ordersの要素数)です。

R6問6(情報セキュリティ)

問6 A社は従業員450名の商社であり,昨年から働き方改革の一環として,在宅でのテレワークを推進している。A社のシステム環境を図1に示す。

・従業員には,一人に1台デスクトップPC(以下,社内PCという)を貸与している。
・従業員が利用するシステムには,自社で開発しA社に設置している業務システムのほかに,次の二つのSaaS(以下,二つのSaaSをA社利用クラウドサービスという)がある。
 1.メール機能,チャット機能及びクラウドストレージ機能をもつグループウェア(以下,A社利用グループウェアという)
 2.オンライン会議サービス
・テレワークでは,従業員の個人所有PC(以下,私有PCという)の業務利用(BYOD)を許可している。
・テレワークでは,社内PC及び私有PCのそれぞれに専用のアプリケーションソフトウェア(以下,専用アプリという)を導入し,社内PCのデスクトップから私有PCに画面転送を行うリモートデスクトップ方式を採用している。
・専用アプリには,リモートデスクトップからPCへのファイルのダウンロード及びファイル,文字列,画像などのコピー&ペーストを禁止する機能(以下,保存禁止機能という)があり,A社では私有PCに対して当該機能を有効にしている。
・業務システムには,社内PCのデスクトップから利用者ID及びパスワードを入力してログインしている。
・A社利用クラウドサービスへのログインは,A社利用クラウドサービス側の設定によってA社の社内ネットワークからだけ可能になるよう制限している。ログインには利用者ID及びパスワードを用いている。

図1 A社のシステム環境(抜粋)

テレワークの定着が進むにつれて,社内PCからインターネットへの接続が極端に遅くなり,業務に支障をきたしているので改善できないかと,従業員から問合せがあった。A社の社内ネットワークとインターネットとの間の通信量を調査したところ,テレワーク導入前に比べ,業務時間帯で顕著に増加していることが判明した。そのため,情報システム部では,テレワークでA社利用クラウドサービスに接続する場合には,A社の社内ネットワークも社内PCも介さずに直接接続することを可能にするネットワークの設定変更を実施することにした。

設問 次の対策のうち,情報システム部に依頼することにしたものはどれか。解答群のうち,最も適切なものを選べ。

解答群
ア A社の社内ネットワークからA社利用クラウドサービスへの通信を監視する。
イ A社の社内ネットワークとA社利用クラウドサービスとの間の通信速度を制限する。
ウ A社利用クラウドサービスにA社外から接続する際の認証に2要素認証を導入する。
エ A社利用クラウドサービスのうち,A社利用グループウェアだけを直接接続の対象とする。
オ 専用アプリの保存禁止機能を無効にする。

解説を開く

テレワークでA社利用クラウドサービスに接続する場合には,A社の社内ネットワークも社内PCも介さずに直接接続することを可能にするネットワークの設定変更
・テレワークでは,従業員の個人所有PC(以下,私有PCという)の業務利用(BYOD)を許可している。
上記と関連する選択肢はウだけです。

令和7年度

R7問1

次のプログラム中の【a】と【b】に入れる正しい答えの組合せを,解答群の中から選べ。
関数 function1 が受け取る引数と,関数 function2 が受け取る引数とが同じとき,二つの関数は同じ値を返す。ここで,引数 n と引数 m は正の整数であり,引数 m は引数 n よりも 10 以上大きい数とする。

〔プログラム〕

○整数型: function1(整数型: n, 整数型: m)
  整数型: count ← 0
  整数型: i
  for (i を n から m まで 1 ずつ増やす)
    if ((i mod 4) が 0 と等しい)
      count ← count + 1
    endif
  endfor
  return count


○整数型: function2(整数型: n, 整数型: m)
  整数型: count ← 0
  整数型: tempN ← n
  整数型: i, j

  for (【a】)
    if ((tempN mod 4) が 0 と等しい)
      繰返し処理を終了する
    endif
    tempN ← tempN + 1
  endfor

  for (【b】)
    count ← count + 1
  endfor

  return count
選択肢 a b
iを1から2まで1ずつ増やす jをnから始めてmを超えない範囲でtempNずつ増やす
iを1から2まで1ずつ増やす jをtempNからmまで1ずつ増やす
iを1から2まで1ずつ増やす jをtempNから始めてmを超えない範囲で4ずつ増やす
iを1から3まで1ずつ増やす jをnから始めてmを超えない範囲でtempNずつ増やす
iを1から3まで1ずつ増やす jをtempNからmまで1ずつ増やす
iを1から3まで1ずつ増やす jをtempNから始めてmを超えない範囲で4ずつ増やす

✓R7問2(100円玉)

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

関数 change は,10 より大きい整数を引数 n で受け取り,1 円玉,5 円玉,10 円玉を使ってちょうど n 円にする組合せの総数を返す。

例えば,12 円にする組合せは,次のように数えられる。
10 円玉を使わない場合には,1 円玉と 5 円玉だけでちょうど 12 円にすることになる。その組合せは,使える 5 円玉の枚数が 0 以上(12 ÷ 5 の商)以下なので,(12 ÷ 5 の商)+ 1 = 3 通りある。
同様に,10 円玉を 1 枚使う場合には,1 円玉と 5 円玉だけでちょうど 2 円にすることになり,その組合せは(2 ÷ 5 の商)+ 1 = 1 通りある。
10 円玉を 2 枚以上使う組合せはない。
よって,1 円玉,5 円玉,10 円玉を使ってちょうど 12 円にする組合せは,3 + 1 = 4 通りである。

〔プログラム〕

○整数型: change(整数型: n)
  整数型: count ← 0
  整数型: rest ← n
  while (【 】)
    count ← count + (rest ÷ 5 の商) + 1
    rest ← rest - 10
  endwhile
  return count
  ```

解答群
ア rest ≧ 0
イ rest ≧ 5
ウ rest ≧ 10
エ rest > 0
オ rest > 5
カ rest > 10

### ✓R7問3(スタック)

次のプログラム中の【 a 】と【 b 】に入れる正しい答えの組合せを、解答群の中から選べ。 ここで、配列の要素番号は 1 から始まる。 関数 push は,引数で与えられた整数をスタックに格納する。格納できる場合は true を返し,格納できなかった場合は false を返す。 関数 pop は,スタックから値を取り出して返す。スタックが空のときは未定義の値を返す。 スタックを,要素数が 4 である大域の整数型の配列 stack,及び次に値を格納する位置を示す大域の変数 stackPos で表現する。スタックの初期状態を図に示す。プログラムでは,配列の領域外を参照してはならないものとする。 【図 スタックの初期状態】 | 要素番号 | 1 | 2 | 3 | 4 | | :-: | :-: | :-: | :-: | :-: | | stack | 4 | 3 | 未定義の値 | 未定義の値 | | | | | ↑<br>stackPos | | 注記 網掛けはその要素が未定義であることを示す。

大域:整数型:stackPos ← 3
大域:整数型の配列:stack ← {4, 3, 未定義の値, 未定義の値}

○ 論理型:push(整数型:inputData)
if (stackPos ≤ stack の要素数)
stack[ 【 a 】 ] ← inputData
stackPos ← stackPos + 1
return true
else
return false
endif

○ 整数型:pop()
整数型:popData ← 未定義の値
if (stackPos > 1)
stackPos ← 【 b 】
popData ← stack[stackPos]
stack[stackPos] ← 未定義の値
endif
return popData


解答群

|\|   | a            | b            |
| - | ------------ | ------------ |
| ア | stackPos     | stackPos + 1 |
| イ | stackPos     | stackPos − 1 |
| ウ | stackPos − 1 | stackPos + 1 |
| エ | stackPos − 1 | stackPos − 1 |

<details markdown="1"><summary>解説を開く</summary>

正解はイです。  

push時  
例えば1を引数として実行した場合、格納直後のstackおよびstackPosは以下となります。

| 1   | 2   | 3          | 4          |
| :-: | :-: | :--------: | :--------: |
| 4   | 3   | 1 | 未定義の値 |
|     |     |     ↑<br>stackPos       |     |

よって、`stack【 a 】 ← inputData`は`stack[stackPos] ← inputData`となります。  
(stackPosはこの後の処理`stackPos ← stackPos + 1`で1増えます。)

pop時  

| 1   | 2   | 3          | 4          |
| :-: | :-: | :--------: | :--------: |
| 4   | 未定義の値`   | 未定義の値 | 未定義の値 |
|     | ↑<br>stackPos    |            |     |

stackPosは3から2に変化します。  
よって、`stackPos ← 【 b 】`は`stackPos ← stackPos - 1`となります。

キューは、先入れ先出しのデータ構造です。

例1:ロケット鉛筆

</details>

### ✓R7問4(分岐&ループのネスト)

次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。 ここで,配列の要素番号は 1 から始まる。 関数 search は,二つの文字型の配列を,それぞれ引数 data 及び key で受け取り,data から key の要素の並びと同じ並びを全て探し,その先頭の要素番号を全て格納した配列を返す。 見つからなければ,要素数 0 の配列を返す。 関数 search を`search({"a","b","a","b","c","a","b","c"}, {"a","b","c"})`として呼び出すと, `/ *** β *** /` の行の条件式が真となる回数は【 】回である。 ```text /* key は,要素数 1 以上の配列である */ ○ 整数型の配列: search(文字型の配列: data, 文字型の配列: key) 整数型: i, j, lenData, lenKey 整数型の配列: result ← {} // 要素数0の配列 lenData ← data の要素数 lenKey ← key の要素数 /* (lenData − lenKey + 1) が0以下のときは繰返し処理を実行しない */ for (i を 1 から (lenData − lenKey + 1) まで 1 ずつ増やす) for (j を 1 から lenKey まで 1 ずつ増やす) // α if (data[i + j − 1] が key[j] と等しい) /*** β ***/ if (j が lenKey と等しい) result の末尾に i の値を追加する endif else α の行から始まる繰返し処理を終了する endif endfor endfor return result

解答群
ア 1 イ 2 ウ 3 エ 4 オ 5
カ 6 キ 7 ク 8 ケ 9 コ 10

解説を開く

正解はク8です。

関数 search は,二つの文字型の配列を,それぞれ引数 data 及び key で受け取り,data から key の要素の並びと同じ並びを全て探し,その先頭の要素番号を全て格納した配列を返す。

上記より、すべて同じ並びは{“a”,”b”,“a”,”b”,”c”,“a”,”b”,”c”}、先頭の要素番号は3,6なので、戻り値の配列は{3,6}となると読み取れます。

  • 配列data{“a”,”b”,”a”,”b”,”c”,”a”,”b”,”c”}から、key{“a”,”b”,”c”}と同じ並びをすべて探す
  • その先頭の要素番号を格納した配列を返す

この2つを行う処理であると頭に入れた上で、トレースしていきます。

①トレース表の作成
data

1 2 3 4 5 6 7 8
a b a b c a b c

ここで間違えると、このあとどれだけ頑張っても絶対に正解できません。焦らず丁寧に書きましょう。
「えー、びー、えー、びー・・」と小声で唱えながら書くと間違えにくいです。

key

1 2 3
a b c

トレース表

i (1~6) j (1~3) lenData lenKey if(data[i + j – 1] = key[j])
8 3

繰り返し条件である
`for (i を 1 から (lenData − lenKey + 1) まで 1 ずつ増やす)`
`for (j を 1 から lenKey まで 1 ずつ増やす)`
は、トレース表を書く時点で計算し、具体的な値を記入しましょう。

(計算の内訳)
iの(1~6)の6は、`lenData − lenKey + 1`の計算結果(8 – 3 + 1)です。

if (data[i + j − 1] が key[j] と等しい)がfalseの場合、内側の繰り返しが終了します。そのため、都度判定しながらトレースします。

i (1~6) j (1~3) lenData lenKey data[i + j – 1] = key[j]
1
1 data[1+1-1] = key[1]
a = a

最後までトレースすると、以下となります。

i (1~6) j (1~3) data[i + j – 1] = key[j]
1
1 data[1+1-1] = key[1]
1
a     a
2 data[1+2-1] = key[2]
2
b     b
3 data[1+3-1] = key[3]
3
a     c
×
2
1 data[2+1-1] = key[1]
2
b     a
×
3
1 data[3+1-1] = key[1]
3
a     a
2 data[3+2-1] = key[2]
4
b     b
3 data[3+3-1] = key[3]
5
c     c
4
1 data[4+1-1] = key[1]
4
b     a
×
5
1 data[5+1-1] = key[1]
5
c     a
×
6
1 data[6+1-1] = key[1]
6
a     a
2 data[6+2-1] = key[2]
7
b     b
3 data[6+3-1] = key[3]
8
c     c

data[i + j - 1] = key[j]が真となった回数は8回(ク)です。

Point:ヒントを見落とさず、効率的にトレースする

  • 配列data{“a”,”b”,”a”,”b”,”c”,”a”,”b”,”c”}から、key{“a”,”b”,”c”}と同じ並びをすべて探す
  • その先頭の要素番号を格納した配列を返す

この2つから、

  • key[j]はa→b→cの順に判定する
  • data[i + j – 1]はiを起点として、配列dataの要素を順に判定する。

とわかると、より速くトレースできます。

この後の処理は、判定が真だったとしても`result の末尾に i の値を追加する`だけであり、`if (data[i + j − 1] が key[j] と等しい)`の判定に影響がありません。そのため、`if (j が lenKey と等しい)`以降のトレースは省略します。

for (j を 1 から lenKey まで 1 ずつ増やす) 
  if (data[i + j − 1] が key[j] と等しい)   /*** β ***/
      //(省略可能)
  else
      α の行から始まる繰返し処理を終了する
  endif
end for

Point:値を変えてトレースしてみよう

呼び出す際の引数を変えてトレースすると、よい練習になります。
A:search({"a","c","a","b","a","b","c","c"}, {"a","b","c"})
B:search({"a","b","a","b","c","a","b","c"}, {"a","b"})

なお、正解はdata 内で key の並びが連続して現れる回数です。

A:正解は6回
search({"a",”c”,"a","b","a","b","c",“c”}, {“a”,”b”,”c”})

B:正解は6回
search({"a","b","a","b",”c”,"a","b",”c”}, {“a”,”b”})

✓R7問5(予防接種-トレース&読解)

次の記述中の【a】と【b】に入れる正しい答えの組合せを,解答群の中から選べ。ここで,配列の要素番号は 1 から始まる。

予防接種の病気 X に対する予防効果を調査するために集めたデータの集計結果を基に,病気 X にかかるかどうかが,予防接種の有無に影響されないと仮定した場合の人数を計算する。この人数を理論度数という。表 1 に集計結果の例を示し,表 2 に表 1 を基に計算した理論度数を示す。

関数 f は,引数 data で受け取った集計結果を基に計算した理論度数を返す。引数と戻り値は二次元配列で,その行が表の行,その列が表の列に対応する。

表1 集計結果の例(単位 人)

病気Xにかからなかった 病気Xにかかった
予防接種を受けた 82 6
予防接種を受けていない 58 8

表2 表1を基に計算した理論度数(単位 人)

病気Xにかからなかった 病気Xにかかった
予防接種を受けた a (網掛け)
予防接種を受けていない (網掛け) b

注記 網掛けの部分は表示していない。

〔プログラム〕

○実数型の二次元配列:f(実数型の二次元配列:data)
 実数型:t ← dataの要素の和
 整数型:row ← dataの行数
 整数型:col ← dataの列数
 実数型の二次元配列:result ← {row行col列の 未定義の値}
 整数型:r, c
 for(r を 1 から row まで 1 ずつ増やす)
  for(c を 1 から col まで 1 ずつ増やす)
   result[r, c] ← (dataの行番号rの要素の和) × (dataの列番号cの要素の和) ÷ t
  endfor
 endfor
 return result

解答群

a b
44 33
58 8
70 7
75 2
80 6
80 8
82 6
解説を開く

引数 data で受け取った集計結果を基に計算した理論度数を返すとあるため、表1 集計結果の例をdataとして、トレースします。

①トレース表の作成

data

1 2
1 82 6
2 58 8

result

1 2
1
2

トレース表

t row col r c result[r, c] ← (dataの行rの和) × (dataの列cの和) ÷ t
154 2 2

「要素の和」が見慣れない表現ですが、すべての要素の合計(82+58+6+8=154)です。
プログラムの`result[r, c] ← (dataの行番号rの要素の和) × (dataの列番号cの要素の和) ÷ t`で、`行番号rの要素の和“列番号cの要素の和`もヒントになります。
仮に要素番号と間違えた場合も、`(dataの行rの和) × (dataの列cの和) ÷ t`の計算結果が大きな値になりすぎてしまい、そこで気づけるはずです。

②1周目

t row col r c result[r, c] ← (dataの行rの和) × (dataの列cの和) ÷ t
154 2 2
1 1 result[1,1] ← (dataの行1の和) × (dataの列1の和) ÷ t
(82+6) × (82+58) ÷ 154
88 × 140 ÷ 154
88✕10÷11
80

result

1 2
1 80
2

この時点で正解はオ(80,8)かカ(80,6)のどちらかです。

③4周目(r=2, c=2)

bはresult[2,2]なので、result[1,2]、result[2,1]は省略します。
result[1,2]、result[2,1]は網掛けになっているため、計算したとしても検証にならず、役に立ちません。

t row col r c result[r, c] ← (dataの行rの和) × (dataの列cの和) ÷ t
154 2 2
1 1 result[1,1] ← (dataの行1の和) × (dataの列1の和) ÷ t
(82+6) × (82+58) ÷ 154
88 × 140 ÷ 154
88×10÷11
80
2 2 result[2,2] ← (dataの行2の和) × (dataの列2の和) ÷ t
(58+8) × (6+8) ÷ 154
66 × 14 ÷ 154
66✕1÷11
6

約分しながら、効率的に計算します。
88 × 140 ÷ 154は、2で約分すると、88 × 70 ÷ 77となり、さらに7で約分すると、88 × 10 ÷ 11となります。
66 × 14 ÷ 154は、2で約分すると、66 × 7 ÷ 77となり、さらに7で約分すると、66 × 1 ÷ 11となります。

result

1 2
1 80
2 6

よって正解はオ(80,6)です。

R7問6

問6 A社は従業員200名の電子機器メーカーである。東京に本社があり,新潟に工場がある。

A社では,ファイルサーバを図1のように運用している。

・ファイルサーバは本社と工場のサーバルームに設置している。
・ファイルサーバは,磁気テープを使用してファイルのバックアップを取得している。
・土曜日の午前2時からフルバックアップを取得し,翌週の火曜日と木曜日の午前2時から増分バックアップを取得している。
・情報システム部の担当者は毎週月曜日,火曜日,木曜日の朝10時頃,バックアップジョブの実行結果の確認と磁気テープの交換を行い,磁気テープは耐火金庫に保管している。
・磁気テープには上書きモードでバックアップを取得し,1か月分の磁気テープを世代管理している。
・これまで,フルバックアップからのリストアには平均して4時間,1回の増分バックアップからは平均して0.25時間掛かっている。
・A社はICT継続のための試験を実施しており,ファイルサーバも試験対象である。

注記 事業影響度分析の結果に基づき,ファイルサーバは,72時間の目標復旧時点(RPO)と120時間の目標復旧時間(RTO)が要求事項として定められている。

図1 A社のファイルサーバの運用

A社はISMS認証を取得しており,最高情報セキュリティ責任者(CISO)を中心に情報セキュリティに取り組み,定期的に,情報セキュリティリスクアセスメントを行っている。今般,ISMS認証基準がJIS Q 27001:2023に改正されたことを受け,情報セキュリティリーダーのBさんは,新基準への移行審査に向けて準備することになった。改正によって新たに追加された情報セキュリティ管理策について,Bさんは情報システム部の担当者に取組状況を確認し,その評価結果を表1にまとめた。

表1 Bさんの評価結果(抜粋)

項番1
情報セキュリティ管理策:(事業継続のためのICTの備え)事業継続の目的及びICT継続の要求事項に基づいて,ICTの備えを計画し,実施し,維持し,試験しなければならない。
評価結果:実施している

Bさんは,移行審査前の内部監査で,内部監査室から表1の項番1に関するファイルサーバの運用について何点か質問を受け,表2のとおり回答した。
表2 内部監査室へのBさんの回答(抜粋)

項番 Bさんの回答
1 例えば,金曜日の正午に障害が発生した場合,少なくとも【a1】の時点のデータは復元しなければならない。
2 例えば,木曜日の正午に障害が発生し,ファイルサーバの全データが消失したとすると,バックアップからのリストアには【a2】時間掛かると予想される。
3 ICT継続の計画書は,【a3】が承認している。

解答群

a1 a2 a3
月曜日の正午 4.25 CISO
月曜日の正午 4.25 情報システム部の担当者
月曜日の正午 4.25 内部監査室長
月曜日の正午 4.50 CISO
月曜日の正午 4.50 情報システム部の担当者
火曜日の正午 4.25 情報システム部の担当者
火曜日の正午 4.25 内部監査室長
火曜日の正午 4.50 CISO
火曜日の正午 4.50 情報システム部の担当者
火曜日の正午 4.50 内部監査室長
解説を開く

正解はク。
a1:金曜正午から72時間以内は、火曜日の正午

a2:
フルバックアップ+火+木

a3:CISO
問題文上、内部監査室長は登場しない
承認するのは偉い人なので、情報システムの担当者ではない。

a1とa3が分かれば、解ける。

タイトルとURLをコピーしました