読み込み中...
読み込み中...
読み込み中...
読み込み中...
読み込み中...
基本情報技術者試験の科目Bでは、擬似言語 (ぎじげんご)で書かれたプログラムを読み解く問題が出題されます。擬似言語とは、特定のプログラミング言語ではなく、試験用に定められた独自の記法です。
C言語やJavaなどの実際の言語を知らなくても、擬似言語の 仕様(ルール) さえ覚えれば問題を解くことができます。このセクションでは、擬似言語の基本的な構文を一つずつ丁寧に学んでいきます。
擬似言語では、変数を使う前に 型 を指定して宣言します。代入には ← 記号を使います。
整数型: x
整数型: y
x ← 10
y ← x + 5
上の例では、整数型の変数 x と y を宣言し、x に 10 を代入した後、y に x + 5(= 15)を代入しています。
| 型 | 説明 | 値の例 |
|---|---|---|
| 整数型 | 整数値を格納 | 0, -3, 42 |
| 実数型 | 小数を含む数値を格納 | 3.14, -0.5 |
| 文字型 | 1文字を格納 | 'A', '9' |
| 文字列型 | 文字の並びを格納 | "Hello" |
| 論理型 | 真(true)または偽(false) | true, false |
代入は 右辺を計算してから左辺に格納 します。数学の等号とは意味が違います。
整数型: a
a ← 3
a ← a + 1
この場合、最初に a は 3 になり、次の行で a + 1(= 4)が計算されて a に格納されます。最終的に a は 4 です。
代入の右辺には 算術演算子 を使った式が書けます。
| 演算子 | 意味 | 例 |
|---|---|---|
| + | 加算 | x + 3 |
| - | 減算 | x - 1 |
| × | 乗算 | x × 2 |
| ÷ | 整数除算(商) | 7 ÷ 2 → 3 |
| mod | 剰余(余り) | 7 mod 2 → 1 |
条件によって処理を分けるには if 文を使います。
if (条件)
処理
endif
条件が 真(true) のときだけ、処理が実行されます。
if (条件)
条件が真のときの処理
else
条件が偽のときの処理
endif
複数の条件を順に判定するときは elseif を使います。
整数型: score
score ← 75
if (score ≧ 80)
print("A")
elseif (score ≧ 60)
print("B")
else
print("C")
endif
この例では、score は 75 です。最初の条件 score ≧ 80 は偽なので飛ばされ、次の score ≧ 60 が真なので "B" が出力されます。else の処理は実行されません。
条件式で使う演算子をまとめます。
| 比較演算子 | 意味 | 例 |
|---|---|---|
| = | 等しい | x = 10 |
| ≠ | 等しくない | x ≠ 0 |
| > | より大きい | x > 5 |
| < | より小さい | x < 100 |
| ≧ | 以上 | x ≧ 60 |
| ≦ | 以下 | x ≦ 99 |
| 論理演算子 | 意味 | 例 |
|---|---|---|
| and | かつ(両方真で真) | x > 0 and x < 100 |
| or | または(片方真で真) | x = 0 or x = 1 |
| not | 否定(真偽を反転) | not (x = 0) |
同じ処理を何度も行うには繰り返し構文を使います。擬似言語には3種類の繰り返しがあります。
条件を先に判定 し、真の間だけ処理を繰り返します。条件が最初から偽なら1回も実行されません。
整数型: i
i ← 1
while (i ≦ 5)
print(i)
i ← i + 1
endwhile
出力: 1, 2, 3, 4, 5
処理を先に実行してから条件を判定 します。最低1回は必ず実行されます。
整数型: i
i ← 1
do
print(i)
i ← i + 1
while (i ≦ 5)
出力は while 文と同じ 1, 2, 3, 4, 5 ですが、仮に i ← 10 で始めた場合、while 文は何も出力しないのに対し、do-while 文は 10 を1回出力 します。
| while(前判定) | do-while(後判定) | |
|---|---|---|
| 判定タイミング | ループの先頭 | ループの末尾 |
| 最低実行回数 | 0回 | 1回 |
| 使い分け | 実行しない場合があるとき | 最低1回は実行したいとき |
繰り返し回数が決まっているときに使います。初期化、条件、更新 の3つを1行にまとめて書きます。
整数型: i
for (i を 1 から 5 まで 1 ずつ増やす)
print(i)
endfor
出力: 1, 2, 3, 4, 5
for 文は while 文で書き直すこともできます。上の for 文は、先ほどの while 文の例と同じ動作です。
繰り返しの中に繰り返しを書くことを ネスト と呼びます。
整数型: i, j
for (i を 1 から 3 まで 1 ずつ増やす)
for (j を 1 から 3 まで 1 ずつ増やす)
print(i × j)
endfor
endfor
出力: 1, 2, 3, 2, 4, 6, 3, 6, 9(九九の一部に相当)
外側の i が 1 のとき内側の j が 1, 2, 3 と回り、次に i が 2 のとき j が 1, 2, 3 と回る、という動作です。合計 3 × 3 = 9 回の print が実行されます。
配列は、複数のデータをまとめて管理するための仕組みです。擬似言語では 添字(インデックス)は 0 から始まります 。
整数型の配列: A[5]
A[0] ← 10
A[1] ← 25
A[2] ← 33
A[3] ← 47
A[4] ← 52
| 添字 | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| 値 | 10 | 25 | 33 | 47 | 52 |
整数型の配列: A[] ← {10, 25, 33, 47, 52}
整数型: i, sum
sum ← 0
for (i を 0 から 4 まで 1 ずつ増やす)
sum ← sum + A[i]
endfor
print(sum)
出力: 167(= 10 + 25 + 33 + 47 + 52)
この例では、ループ変数 i を 0 から 4 まで変化させて、配列 A の全要素を順番にたどっています。
2つの要素を入れ替えるには、一時変数(temp)を使います。
整数型: temp
temp ← A[0]
A[0] ← A[3]
A[3] ← temp
実行前: A = {10, 25, 33, 47, 52} 実行後: A = {47, 25, 33, 10, 52}
この「一時変数を使った交換」はソートアルゴリズムの基本操作として頻出します。
処理をまとめて名前を付けたものを 手続き または 関数 と呼びます。関数は値を返し、手続きは値を返しません。
擬似言語では ○ 記号を使って関数を定義します。
○整数型: add(整数型: a, 整数型: b)
return a + b
この関数は、引数 a と b を受け取り、その合計を返します。○ の直後に 戻り値の型 を書きます。
整数型: result
result ← add(3, 5)
print(result)
出力: 8
関数 add に 3 と 5 を渡すと、内部で a + b(= 8)が計算され、return で呼び出し元に返されます。
○printGreeting(文字列型: name)
print("こんにちは、" + name + "さん")
printGreeting("太郎")
出力: こんにちは、太郎さん
手続きには return がなく、戻り値の型も書きません。
擬似言語では、引数の渡し方に2種類あります。
| 渡し方 | 記法 | 動作 |
|---|---|---|
| 値渡し | そのまま書く | 値のコピーを渡す。関数内で変更しても呼び出し元は変わらない |
| 参照渡し | 仕様で指定 | 変数そのものを渡す。関数内で変更すると呼び出し元も変わる |
○swap(整数型の配列: arr, 整数型: i, 整数型: j)
整数型: temp
temp ← arr[i]
arr[i] ← arr[j]
arr[j] ← temp
配列は通常 参照渡し されるため、関数内での変更が呼び出し元の配列にも反映されます。この swap 関数はソートの実装でよく登場します。
関数を呼び出すと、プログラムの実行は 関数の中に移動 し、return で 呼び出し元に戻ります 。このとき、戻り値が呼び出し元の式の値として使われます。
ポイント
擬似言語はFE試験科目B専用の記法で、変数宣言は 型名: 変数名 、代入は ← を使う。条件分岐は if / elseif / else / endif で構成し、上から順に条件を判定して最初に真になったブロックだけを実行する。繰り返しは while (前判定・0回の可能性あり)、 do-while (後判定・最低1回実行)、 for (回数が決まっているとき)の3種類。配列の添字は 0始まり で、要素交換には一時変数を使う。関数は ○戻り値の型: 関数名(引数) で定義し、 return で値を返す。配列は参照渡しされるため、関数内の変更が呼び出し元に反映される。
用語
セクション1で学んだ擬似言語の構文を使い、代表的なアルゴリズムを実際に擬似言語で実装していきます。科目Bでは、アルゴリズムの「考え方」だけでなく、 擬似言語のコードとして正しく読み書きできるか が問われます。
ここでは探索、ソート、データ構造の3分野について、擬似言語での実装を学びます。
線形探索 は、配列の先頭から順に目的の値を探す最も基本的なアルゴリズムです。
○整数型: linearSearch(整数型の配列: A, 整数型: n, 整数型: target)
整数型: i
for (i を 0 から n - 1 まで 1 ずつ増やす)
if (A[i] = target)
return i
endif
endfor
return -1
A: 探索対象の配列n: 配列の要素数target: 探したい値配列 A = {10, 25, 33, 47, 52}、target = 33 の場合:
| i | A[i] | A[i] = 33 ? | 動作 |
|---|---|---|---|
| 0 | 10 | 偽 | 次へ |
| 1 | 25 | 偽 | 次へ |
| 2 | 33 | 真 | return 2 |
結果: 2 が返される(A[2] に target がある)
配列の末尾に探索値を追加(番兵)することで、ループ内の「配列の範囲チェック」を省略できます。
○整数型: linearSearchSentinel(整数型の配列: A, 整数型: n, 整数型: target)
整数型: i
A[n] ← target
i ← 0
while (A[i] ≠ target)
i ← i + 1
endwhile
if (i < n)
return i
else
return -1
endif
番兵があるので while は必ず停止します。ループ終了後、i < n なら元の配列内で見つかったことを意味し、i = n なら番兵に到達した(見つからなかった)ことを意味します。
二分探索 は、ソート済み配列に対して探索範囲を半分に絞り込む高速な探索です。
○整数型: binarySearch(整数型の配列: A, 整数型: n, 整数型: target)
整数型: left, right, mid
left ← 0
right ← n - 1
while (left ≦ right)
mid ← (left + right) ÷ 2
if (A[mid] = target)
return mid
elseif (A[mid] < target)
left ← mid + 1
else
right ← mid - 1
endif
endwhile
return -1
配列 A = {10, 20, 30, 40, 50, 60, 70}(n = 7)、target = 50 の場合:
| 回 | left | right | mid | A[mid] | 判定 | 操作 |
|---|---|---|---|---|---|---|
| 1 | 0 | 6 | 3 | 40 | 40 < 50 | left ← 4 |
| 2 | 4 | 6 | 5 | 60 | 60 > 50 | right ← 4 |
| 3 | 4 | 4 | 4 | 50 | 50 = 50 | return 4 |
結果: 4 が返される。3回の比較で発見できました。線形探索なら5回必要です。
| 項目 | 線形探索 | 二分探索 |
|---|---|---|
| 計算量 | O(n) | O(log n) |
| 前提条件 | なし | ソート済み |
| 100万件での最大比較回数 | 100万回 | 約20回 |
| 実装の難しさ | 簡単 | やや複雑 |
バブルソート は、隣り合う要素を比較して順序が逆なら交換する操作を繰り返すソートです。
○bubbleSort(整数型の配列: A, 整数型: n)
整数型: i, j, temp
for (i を 0 から n - 2 まで 1 ずつ増やす)
for (j を 0 から n - 2 - i まで 1 ずつ増やす)
if (A[j] > A[j + 1])
temp ← A[j]
A[j] ← A[j + 1]
A[j + 1] ← temp
endif
endfor
endfor
i は「何回目のパスか」を表す配列 A = {5, 3, 8, 1}(n = 4)を昇順にソート:
パス 1(i = 0): j は 0 から 2 まで
| j | 比較 | 交換 | 配列の状態 |
|---|---|---|---|
| 0 | A[0]=5 > A[1]=3 | する | {3, 5, 8, 1} |
| 1 | A[1]=5 > A[2]=8 | しない | {3, 5, 8, 1} |
| 2 | A[2]=8 > A[3]=1 | する | {3, 5, 1, 8} |
8 が末尾に確定。
パス 2(i = 1): j は 0 から 1 まで
| j | 比較 | 交換 | 配列の状態 |
|---|---|---|---|
| 0 | A[0]=3 > A[1]=5 | しない | {3, 5, 1, 8} |
| 1 | A[1]=5 > A[2]=1 | する | {3, 1, 5, 8} |
5 が確定。
パス 3(i = 2): j は 0 から 0 まで
| j | 比較 | 交換 | 配列の状態 |
|---|---|---|---|
| 0 | A[0]=3 > A[1]=1 | する | {1, 3, 5, 8} |
完了: {1, 3, 5, 8}
選択ソート は、未ソート部分から最小値を見つけて先頭と交換する操作を繰り返すソートです。
○selectionSort(整数型の配列: A, 整数型: n)
整数型: i, j, minIdx, temp
for (i を 0 から n - 2 まで 1 ずつ増やす)
minIdx ← i
for (j を i + 1 から n - 1 まで 1 ずつ増やす)
if (A[j] < A[minIdx])
minIdx ← j
endif
endfor
if (minIdx ≠ i)
temp ← A[i]
A[i] ← A[minIdx]
A[minIdx] ← temp
endif
endfor
配列 A = {5, 3, 8, 1}(n = 4)を昇順にソート:
| i | 探索範囲 | 最小値 | minIdx | 交換 | 結果 |
|---|---|---|---|---|---|
| 0 | {5, 3, 8, 1} | 1 | 3 | A[0] と A[3] | {1, 3, 8, 5} |
| 1 | {3, 8, 5} | 3 | 1 | 交換なし | {1, 3, 8, 5} |
| 2 | {8, 5} | 5 | 3 | A[2] と A[3] | {1, 3, 5, 8} |
完了: {1, 3, 5, 8}
| 項目 | バブルソート | 選択ソート |
|---|---|---|
| 計算量 | O(n²) | O(n²) |
| 交換回数 | 最悪 O(n²) | 最大 n - 1 回 |
| 安定性 | 安定 | 不安定 |
| 特徴 | 交換が多いが実装が最も簡単 | 交換回数が少ない |
スタック は LIFO(後入れ先出し)のデータ構造です。配列を使って実装できます。
整数型の配列: stack[100]
整数型: top
top ← -1
○push(整数型: value)
top ← top + 1
stack[top] ← value
○整数型: pop()
整数型: value
value ← stack[top]
top ← top - 1
return value
○論理型: isEmpty()
return (top = -1)
top はスタックの最上部の添字を管理する変数push は top を1つ増やしてからデータを格納pop はデータを取り出してから top を1つ減らす| 操作 | top | stack の状態 | 戻り値 |
|---|---|---|---|
| push(10) | 0 | {10} | - |
| push(25) | 1 | {10, 25} | - |
| push(33) | 2 | {10, 25, 33} | - |
| pop() | 1 | {10, 25} | 33 |
| pop() | 0 | {10} | 25 |
| isEmpty() | 0 | {10} | false |
| pop() | -1 | {} | 10 |
| isEmpty() | -1 | {} | true |
キュー は FIFO(先入れ先出し)のデータ構造です。配列を使った リングバッファ で効率的に実装できます。
整数型の配列: queue[100]
整数型: head, tail, count
head ← 0
tail ← 0
count ← 0
○enqueue(整数型: value)
queue[tail] ← value
tail ← (tail + 1) mod 100
count ← count + 1
○整数型: dequeue()
整数型: value
value ← queue[head]
head ← (head + 1) mod 100
count ← count - 1
return value
○論理型: isEmpty()
return (count = 0)
head はデータを取り出す位置(先頭)tail はデータを追加する位置(末尾)mod 100 で添字が配列の末尾を超えたら先頭に戻る(循環)count で要素数を管理| 操作 | head | tail | count | queue の状態 | 戻り値 |
|---|---|---|---|---|---|
| enqueue(10) | 0 | 1 | 1 | {10} | - |
| enqueue(25) | 0 | 2 | 2 | {10, 25} | - |
| enqueue(33) | 0 | 3 | 3 | {10, 25, 33} | - |
| dequeue() | 1 | 3 | 2 | {25, 33} | 10 |
| dequeue() | 2 | 3 | 1 | {33} | 25 |
| enqueue(47) | 2 | 4 | 2 | {33, 47} | - |
スタックと違い、先に入れたデータ(10)が先に取り出されるのがキューの特徴です。
ポイント
擬似言語で基本アルゴリズムを実装できることが科目Bの核心。線形探索 は for ループで先頭から順に比較し、見つかったら添字を return する。二分探索 は left・right・mid の3変数で探索範囲を管理し、 mid ← (left + right) ÷ 2 で中央を計算する。バブルソート は二重ループで隣接要素を比較・交換し、内側ループの上限が n - 2 - i である理由を理解する。選択ソート は最小値の添字 minIdx を記録してからまとめて交換する。スタック は top 変数で最上部を管理し push/pop を実装する。キュー は head・tail・count と mod によるリングバッファで enqueue/dequeue を実装する。
用語
科目Bの問題を確実に解くための最も強力な武器が トレース です。トレースとは、プログラムの実行を1行ずつ追いかけて、各変数の値の変化を記録する作業です。
擬似言語の問題では「この関数の戻り値は何か」「空欄に入るコードは何か」といった形式が出題されます。頭の中だけで考えるとミスしやすいため、 トレース表 を書いて確実に正解にたどり着く方法を身につけましょう。
トレース表は、プログラムの各ステップで変数がどう変化するかを表にまとめたものです。
整数型の配列: A[] ← {3, 7, 2, 5}
整数型: i, sum, n
n ← 4
sum ← 0
for (i を 0 から n - 1 まで 1 ずつ増やす)
sum ← sum + A[i]
endfor
print(sum)
トレース表:
| ステップ | i | sum | A[i] | 処理内容 |
|---|---|---|---|---|
| 初期化 | - | 0 | - | sum ← 0 |
| ループ1 | 0 | 3 | 3 | sum ← 0 + 3 |
| ループ2 | 1 | 10 | 7 | sum ← 3 + 7 |
| ループ3 | 2 | 12 | 2 | sum ← 10 + 2 |
| ループ4 | 3 | 17 | 5 | sum ← 12 + 5 |
| 終了 | - | 17 | - | print(17) |
出力: 17
A[i] の値だけ書く列を用意するもう少し複雑な例として、二分探索をトレースしてみましょう。
○整数型: binarySearch(整数型の配列: A, 整数型: n, 整数型: target)
整数型: left, right, mid
left ← 0
right ← n - 1
while (left ≦ right)
mid ← (left + right) ÷ 2
if (A[mid] = target)
return mid
elseif (A[mid] < target)
left ← mid + 1
else
right ← mid - 1
endif
endwhile
return -1
呼び出し: binarySearch({5, 12, 18, 25, 33, 41, 50}, 7, 41)
トレース表:
| 回 | left | right | mid | A[mid] | 判定 | 操作 |
|---|---|---|---|---|---|---|
| 初期 | 0 | 6 | - | - | - | - |
| 1 | 0 | 6 | 3 | 25 | 25 < 41 → 真 | left ← 4 |
| 2 | 4 | 6 | 5 | 41 | 41 = 41 → 真 | return 5 |
結果: 5 が返される。A[5] = 41 が見つかった。
呼び出し: binarySearch({5, 12, 18, 25, 33, 41, 50}, 7, 20)
| 回 | left | right | mid | A[mid] | 判定 | 操作 |
|---|---|---|---|---|---|---|
| 初期 | 0 | 6 | - | - | - | - |
| 1 | 0 | 6 | 3 | 25 | 25 > 20 | right ← 2 |
| 2 | 0 | 2 | 1 | 12 | 12 < 20 | left ← 2 |
| 3 | 2 | 2 | 2 | 18 | 18 < 20 | left ← 3 |
| 4 | 3 | 2 | - | - | left > right | ループ終了 |
結果: -1 が返される(見つからない)。left > right になった時点でループが終了する点に注目してください。
再帰関数のトレースは、関数が自分自身を呼び出すたびに新しいトレースが始まる と考えると整理しやすくなります。
○整数型: factorial(整数型: n)
if (n ≦ 1)
return 1
endif
return n × factorial(n - 1)
呼び出し: factorial(4)
再帰の呼び出しを ツリー で表現すると次のようになります。
トレース表(呼び出しの深さで整理):
| 深さ | 呼び出し | n | n ≦ 1 ? | 戻り値 |
|---|---|---|---|---|
| 1 | factorial(4) | 4 | 偽 | 4 × 6 = 24 |
| 2 | factorial(3) | 3 | 偽 | 3 × 2 = 6 |
| 3 | factorial(2) | 2 | 偽 | 2 × 1 = 2 |
| 4 | factorial(1) | 1 | 真 | 1 |
再帰は 深さ4 → 3 → 2 → 1 の順に呼び出され、戻り値は 深さ1 → 2 → 3 → 4 の順に返されます。
○整数型: fib(整数型: n)
if (n ≦ 1)
return n
endif
return fib(n - 1) + fib(n - 2)
呼び出し: fib(5)
fib(5) = fib(4) + fib(3) = 3 + 2 = 5
注目すべきは、fib(3) が2回、fib(2) が3回と 同じ計算が繰り返されている 点です。これが再帰の非効率の原因であり、メモ化や動的計画法で改善できます。
科目Bでは、擬似言語プログラムの一部が空欄になっており、正しいコードを選ぶ問題が出題されます。ここでは、穴埋め問題を効率よく解くための戦略を紹介します。
空欄をいきなり埋めようとせず、まず このプログラムは何をしたいのか を理解します。
確認するポイント:
空欄の 直前と直後 のコードから、空欄に何が入るべきかを推測します。
○整数型: findMax(整数型の配列: A, 整数型: n)
整数型: i, max
max ← A[0]
for (i を 1 から n - 1 まで 1 ずつ増やす)
if (【 】)
max ← A[i]
endif
endfor
return max
この関数は「配列の最大値を求める」ものです。max ← A[i] が実行されるのは「A[i] が現在の max より大きいとき」なので、空欄には A[i] > max が入ります。
選択肢を空欄に当てはめて、小さな具体例でトレースします。
例: 上記の findMax に A = {3, 7, 2} を入れて検証
空欄に A[i] > max を入れた場合:
| i | A[i] | max | A[i] > max ? | 更新後の max |
|---|---|---|---|---|
| - | - | 3 | - | 3(初期値) |
| 1 | 7 | 3 | 真 | 7 |
| 2 | 2 | 7 | 偽 | 7 |
戻り値: 7(正しい)
「ループの初回」「ループの最終回」「配列が1要素のとき」など、境界的なケース で正しく動くか確認します。
○整数型: binarySearch(整数型の配列: A, 整数型: n, 整数型: target)
整数型: left, right, mid
left ← 0
right ← 【 】
...
right の初期値は「配列の末尾の添字」なので n - 1 です。もし n を入れてしまうと、A[n] で配列外にアクセスしてしまいます。
全選択肢をトレースする時間がなければ、明らかに間違っているもの を消去します。
消去のチェックポイント:
最後に、穴埋め問題を通しで解いてみましょう。
問題: 以下は配列を昇順にソートするバブルソートのプログラムである。空欄 ア と イ に入る正しいコードを答えよ。
○bubbleSort(整数型の配列: A, 整数型: n)
整数型: i, j, temp
for (i を 0 から n - 2 まで 1 ずつ増やす)
for (j を 0 から 【 ア 】 まで 1 ずつ増やす)
if (A[j] > A[j + 1])
temp ← A[j]
A[j] ← 【 イ 】
A[j + 1] ← temp
endif
endfor
endfor
解き方:
ア について:
バブルソートでは、各パスの後に末尾側の要素が確定します。i 回目のパスでは末尾の i 個が確定済みなので、j の上限は n - 2 - i です。
検証: n = 4, i = 0 のとき j は 0 から 2 まで(A[2] と A[3] を比較するのが最後)。n - 2 - 0 = 2 で正しい。
ア の答え: n - 2 - i
イ について:
3行の交換処理を読みます:
temp ← A[j] — A[j] を退避A[j] ← 【 イ 】 — A[j] に何かを入れるA[j + 1] ← temp — A[j+1] に退避した値を入れるこれは A[j] と A[j+1] の交換です。手順2で A[j] に入るのは A[j+1] の値です。
イ の答え: A[j + 1]
検証: A = {5, 3} で i = 0, j = 0 のとき
結果: {3, 5} — 正しく交換されています。
ポイント
トレースは科目Bを解く最も確実な方法。 トレース表 を書いて変数の変化を1ステップずつ記録する。再帰のトレースでは 呼び出しツリー を描き、基底条件(葉)から戻り値を順に計算する。穴埋め問題は5つの戦略で攻略する: (1) プログラム全体の目的を把握、 (2) 空欄の前後のコードを読む、 (3) 具体的な値でトレースして検証、 (4) 境界値で確認、 (5) 選択肢を消去法で絞る。特に 小さな具体例でトレース する習慣をつけることが、科目Bの得点を安定させる鍵となる。
用語