この記事は基本情報のセキュリティの続きで、科目Bの残りの8割にあたるアルゴリズムとプログラミングを扱います。順次・分岐・反復やフローチャートのような基礎はアルゴリズムの基本に、共通テスト「情報I」の出題範囲は共通テスト「情報I」対策まとめにまとめています。ここではその先の、試験の擬似言語を正確に追う方法に絞ります。

科目Bで問われること

2023年4月からの基本情報技術者試験では、科目Bは20問で、そのうち16問がアルゴリズムとプログラミング、4問が情報セキュリティです(IPAの試験要綱による)。アルゴリズムとプログラミングの問題では、擬似言語で書かれたプログラムが示され、主に次の形で問われます。

  • プログラムの空欄に入れる字句を選ぶ
  • ある引数で呼び出したときの戻り値や、処理を終えたあとの配列の中身を選ぶ
  • ある行が何回実行されるか、繰り返しが何周するかを選ぶ

どの形でも、やることは同じです。プログラムを1行ずつ実行したつもりになり、変数の値がどう変わるかを追います。アルゴリズムの名前を知っていると見通しは立ちますが、答えを決めるのは、問題のプログラムを実際に追った結果です。名前を知っている処理でも、問題ごとに配列の始まりや境界の扱いが少しずつ違うからです。

IPAは、2027年度から新しい試験制度を始める予定を公表しており、基本情報技術者試験のシラバス案も2026年9月に掲載されました。この記事は2026年度時点の制度で書いています。受験する回の出題範囲と出題数は、IPAの基本情報技術者試験のページと新試験制度のシラバス案のページで確認してください。

擬似言語の記述形式

試験の擬似言語は、IPAの「試験で使用する情報技術に関する用語・プログラム言語など」の別紙2「擬似言語の記述形式」で書き方が決まっています。問題文に注記がない限り、この形式で書かれていると考えて読みます。

基本情報技術者試験の擬似言語の記述形式
書き方意味
○手続名又は関数名手続や関数を宣言する
型名: 変数名変数を宣言する(例:整数型: i)
/* 注釈 */ // 注釈注釈(実行されない説明)
変数名 ← 式右の式の値を、左の変数に代入する
手続名又は関数名(引数, …)手続や関数を呼び出し、引数を渡す
if (条件式) 〜 elseif (条件式) 〜 else 〜 endif条件式を上から評価し、最初に真になったものの処理だけを実行する。どれも真でなければ else の処理
while (条件式) 〜 endwhile前判定の繰り返し。先に条件を調べ、真の間繰り返す
do 〜 while (条件式)後判定の繰り返し。処理をしてから条件を調べ、真の間繰り返す
for (制御記述) 〜 endfor制御記述の内容に従って繰り返す(例:for (i を 1 から 5 まで 1 ずつ増やす))

読み違えやすいのは、繰り返しの判定の位置です。while は条件を先に調べるので、最初から偽なら処理は0回です。do 〜 while は処理を先にするので、条件が最初から偽でも1回は実行します。練習問題の問4は、この違いだけで答えが変わる問題です。

演算子の優先度

式の中に演算子が並んだときは、優先度の高いものから計算します。記述形式では次の順です。

擬似言語の演算子と優先度(上ほど高い)
優先度種類演算子
1(高い)式() .
2単項演算子not + −
3乗除mod × ÷
4加減+ −
5関係≠ ≦ ≧ < = >
6論理積and
7(低い)論理和or

mod は割り算の余りで、× や ÷ と同じ優先度です。3 + 17 mod 5 は、先に 17 mod 5 の2を求めて5になります。and が or より先なので、p or q and r は p or (q and r) と読みます。論理型の定数は true と false です。

配列と未定義

配列の要素は a[3] のように [ ] に要素番号を書いて参照し、二次元配列は b[行, 列] の順に書きます。配列の中身をまとめて書くときは {3, 8, 2} のように { } で囲みます。二次元配列なら、内側の { } が1行分です。変数に値が入っていない状態は「未定義」と呼び、「未定義の値」を代入するとその変数は未定義になります。

配列の要素番号が0から始まるか1から始まるかは、記述形式では決まっていません。各問題の注記(「配列の要素番号は1から始まる」など)で示されます。1から始まる問題が多いのですが、0から始まる配列に慣れていると、最後の要素を1つずれて読みがちです。読み始める前に、注記を必ず確かめます。この記事のコードは、どれも要素番号を1から数えます。

記述形式の表には載っていなくても、問題では決まって使われる書き方があります。関数の戻り値を返す return、配列の要素の数を表す aの要素数、○整数型: gcd(整数型: num1, 整数型: num2) のような戻り値と引数の型を付けた宣言、for (i を 1 から n まで 1 ずつ増やす) の制御記述です。どれもIPAが公開している科目Bのサンプル問題で使われており、この記事のコードも同じ書き方にそろえています。整数どうしの ÷ の結果を整数にするかどうかは記述形式では決まっていないので、サンプル問題と同じく、商だけを使う場面では (low + high) ÷ 2 の商 のように書いて示します。試験でも、こうした細かな約束は問題文で説明されるので、問題の前置きの文章を読み飛ばさないようにします。

DNCLとの違い

共通テスト「情報I」のプログラム表記(DNCL)を学んだ人は、考え方の大部分をそのまま使えます。分岐も繰り返しも配列も同じ働きです。違うのは記号で、とくに = の役目が入れ替わる点で引っかかります。下の表の左の列は、このサイトのプログラムのなぞり書きで動く書き方です。

共通テストのDNCLと基本情報技術者試験の擬似言語の書き方の対応
したいことDNCL(情報I)基本情報の擬似言語
代入x = 5x ← 5
等しいか調べるx == 5x = 5
等しくないか調べるx != 5x ≠ 5
分岐もし x > 0 ならば:(字下げで範囲を示す)if (x > 0) 〜 endif
条件で繰り返すx < 10 の間繰り返す:while (x < 10) 〜 endwhile
回数で繰り返すi を 1 から 5 まで 1 ずつ増やしながら繰り返す:for (i を 1 から 5 まで 1 ずつ増やす) 〜 endfor
配列の中身を書くData = [3, 1, 4]a ← {3, 1, 4}
要素の数要素数(Data)aの要素数
割り算の余りx % 3x mod 3
変数の宣言書かない整数型: x
結果を示す表示する(x)関数の戻り値として return x

情報Iを学んだ人が最初に引っかかるのは、if (a[i] = x) を「代入してしまう」と読むことです。基本情報の擬似言語で代入は ← だけなので、= は必ず比べる記号です。逆の向きの失敗もあります。DNCLの字下げに慣れていると、endif や endwhile の位置を見ずに字下げだけで範囲を判断しがちです。範囲は終わりの印で確かめます。もう一つは要素番号で、プログラムのなぞり書きの例題は0から数えますが、基本情報の問題は注記で示された番号から数えます。

トレース表の書き方

トレース表は、プログラムを実行したときの変数の値の移り変わりを、表に書き出したものです。列に変数を並べ、繰り返し1周を1行にします。条件式を調べた結果(真か偽か)の列も作ると、どこで繰り返しを抜けたかが表に残ります。次の関数で試します。

例:1から n までの奇数の和
○整数型: sumOdd(整数型: n)  整数型: s, k  s ← 0  k ← 1  while (k ≦ n)    s ← s + k    k ← k + 2  endwhile  return s

sumOdd(7) を呼び出したとして、3行目と4行目を実行した直後を「開始前」の行に、5行目から7行目までの1周を1行に書きます。

sumOdd(7) のトレース表
周5行目 k ≦ ns(6行目の後)k(7行目の後)
開始前—01
1周目1 ≦ 7 真13
2周目3 ≦ 7 真45
3周目5 ≦ 7 真97
4周目7 ≦ 7 真169
終了9 ≦ 7 偽 → 9行目へ169

戻り値は16です。表にしたことで、4周目の判定 7 ≦ 7 が真になることがはっきりします。頭の中で追うと、ここを「7まで来たから終わり」と読んで、9を答えてしまいます。≦ か < かで周の数が1つ変わるので、この判定は必ず値を当てはめて確かめます。

書くときの決まりは、次の三つで足ります。

  1. 値が変わる変数だけを列にする。一度も変わらない n のような引数は、表の上に1回書けばよい。
  2. 代入した直後の値を書く。同じ周の中で2回変わる変数は、列を2つに分ける。
  3. 条件式は、値を当てはめた形(7 ≦ 7)と真偽を書く。繰り返しを抜けた判定も1行として残す。

表を全部埋める必要はありません。上の例なら、2周ほど書けば「s は奇数を順に足した値、k は次の奇数」という規則が見えます。規則が見えたら残りの周は計算で済ませ、最後の周と、繰り返しを抜ける判定だけをもう一度表で確かめます。

よく出る処理の型

ここからは、科目Bでよく使われる処理を、短いオリジナルのコードと「どこを見るか」で整理します。型を知っていれば、初めて見るプログラムでも「この部分は最大値を探している」と見当を付けてから細部を追えます。ただし、型に当てはめて決めつけるのは危険です。問題のコードは、境界や比べる向きを少し変えてあることがあります。

合計と最大値

○整数型: max(整数型の配列: a)  整数型: m, i  m ← a[1]  for (i を 2 から aの要素数 まで 1 ずつ増やす)    if (a[i] > m)      m ← a[i]    endif  endfor  return m

見るのは、初めの値と繰り返しの始まりの組です。m を a[1] で始めるので、繰り返しは2から始まります。m を0で始めると、全部が負の数の配列で0を返してしまいます。合計なら、和を入れる変数を0で始めて1から繰り返します。比べる記号が > か ≧ かは、同じ値が複数あるときにどれを選ぶかを決めます(練習問題の問5)。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)

線形探索

○整数型: find(整数型の配列: a, 整数型: x)  整数型: i  for (i を 1 から aの要素数 まで 1 ずつ増やす)    if (a[i] = x)      return i    endif  endfor  return −1

先頭から順に比べ、見つかった時点で return します。return を実行すると、繰り返しの途中でも関数はそこで終わります。最後の return −1 に来るのは、全部比べても見つからなかったときだけです。a = {7, 3, 9, 3} で x = 3 を探すと、最初に見つかった2を返し、4番の3は調べません。探索アルゴリズムの用語集も参考になります。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)

二分探索

○整数型: binSearch(整数型の配列: a, 整数型: x)  整数型: low, high, mid  low ← 1  high ← aの要素数  while (low ≦ high)    mid ← (low + high) ÷ 2 の商    if (a[mid] = x)      return mid    elseif (a[mid] < x)      low ← mid + 1    else      high ← mid − 1    endif  endwhile  return −1

配列が小さい順に並んでいることが前提です。調べる範囲を low から high までとし、中央の mid と比べて範囲を半分にします。見るのは3か所で、中央の求め方 (low + high) ÷ 2 の商、範囲の更新 mid + 1 と mid − 1、繰り返しの条件 low ≦ high です。a = {3, 8, 15, 21, 30, 42, 57} で x = 30 を探すと、次のようになります。

binSearch で30を探したときのトレース表
周lowhighmida[mid]比べた結果
11742130より小さい → low ← 5
25764230より大きい → high ← 5
355530一致 → 5を返す

3周目は low と high が同じ5です。条件が low < high だったら、この周に入れず、30を見つけられずに −1 を返します。範囲の更新に +1・−1 が付くのは、mid の位置はもう調べ終わったからです。付けないと、範囲が縮まずに同じ周を繰り返すことがあります(練習問題の問7)。整列済みの配列での比べる回数の少なさは、計算量の考え方につながります。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)/線形探索と二分探索の動きを並べて見る(可視化スタディ)

交換法(バブルソート)

○sort(整数型の配列: a)  整数型: n, i, j, tmp  n ← aの要素数  for (i を n から 2 まで 1 ずつ減らす)    for (j を 1 から i − 1 まで 1 ずつ増やす)      if (a[j] > a[j + 1])        tmp ← a[j]        a[j] ← a[j + 1]        a[j + 1] ← tmp      endif    endfor  endfor

隣どうしを比べ、左が大きければ入れ替えます。内側の繰り返しを1回終えるたびに、残りの中で最も大きい値が右端に移って確定します。そのため、内側の範囲は1周ごとに1つずつ縮みます。見るのは内側の終わり i − 1 で、ここが i だと a[j + 1] が範囲の外を指します。a = {4, 2, 5, 1, 3} を並べると、次のようになります。

sort で {4, 2, 5, 1, 3} を並べたときの外側の繰り返しごとの配列
ij の範囲比べた回数内側を終えた後の a
51〜44{2, 4, 1, 3, 5}
41〜33{2, 1, 3, 4, 5}
31〜22{1, 2, 3, 4, 5}
21〜11{1, 2, 3, 4, 5}

太字は確定した部分です。比べた回数は 4+3+2+1=10回で、配列の中身によらず決まります。入れ替えた回数は中身によって変わり、この例では6回でした。「比べる回数」と「入れ替える回数」のどちらを聞かれているかを、問題文で確かめます。ほかの並べ方はソートアルゴリズムの用語集にまとめています。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)/バブル・挿入・選択・マージ・クイックの各ソートをコマ送りで見る(可視化スタディ)

ユークリッドの互除法

○整数型: gcd(整数型: m, 整数型: n)  整数型: r  while (n ≠ 0)    r ← m mod n    m ← n    n ← r  endwhile  return m

2つの数の最大公約数は、「大きいほうを小さいほうで割った余り」と「小さいほう」の最大公約数に等しい、という性質を繰り返し使います。余りが0になったときの割る数が答えです。gcd(84, 36) なら、1周目に r = 84 mod 36 = 12 で m = 36、n = 12、2周目に r = 0 で m = 12、n = 0 となり、12を返します。

見るのは代入の順番です。m ← n と n ← r を逆にすると、m にも n にも余りが入ってしまいます。値を移す順番の問題は交換法の tmp と同じ形で、トレース表で各行の直後の値を書くと間違いに気づけます。返すのが n ではなく m であることも、繰り返しを抜けたときに n が0であることから確かめられます。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)

再帰

○整数型: fact(整数型: n)  if (n ≦ 1)    return 1  endif  return n × fact(n − 1)

関数の中で同じ関数を呼び出すのが再帰です。関数を呼び出すと、呼んだ側は戻り値が返ってくるまで計算を止めて待ちます。トレース表では、呼び出しを1段ずつ下に積み、戻り値が決まったら下の段から順に上へ返します。

fact(4) を呼び出したときの呼び出しと戻り値
段呼び出し待っている計算戻り値
1fact(4)4 × fact(3)4 × 6 = 24
2fact(3)3 × fact(2)3 × 2 = 6
3fact(2)2 × fact(1)2 × 1 = 2
4fact(1)なし(n ≦ 1 が真)1

表は上から下へ書き、戻り値の列は下から上へ埋めます。見るのは、呼び出しが止まる条件(ここでは n ≦ 1)と、呼び出すたびに引数が止まる条件へ近づいているかです。fact(n − 1) が fact(n) だったら、呼び出しは終わりません。

このコードと同じ型の例題を1行ずつ動かす(プログラムのなぞり書きの基本情報モード)/再帰の呼び出しが積まれて戻る様子を見る(可視化スタディ)

空欄を埋める問題の解き方

空欄の問題では、プログラムの目的が問題文に書いてあります。選択肢をにらんで「これが正しそうだ」と決めると、似た選択肢の間で迷います。確実なのは、選択肢を1つずつ空欄に入れ、小さな入力で1周だけトレースする方法です。

  1. 問題文から、関数が何を返すべきかを一文で書き出す。同じ値が複数あるとき、見つからないときの扱いも拾う。
  2. 要素が3個ほどの小さな入力を自分で決める。正しい答えを先に手で求めておく。
  3. 選択肢を入れて、1周目をトレースする。ここで明らかにおかしい選択肢を外す。
  4. 残った選択肢を、境界で確かめる。最後の周、繰り返しを抜ける判定、要素が0個や1個のとき。

たとえば、配列の合計を求めるプログラムの for (i を 1 から [空欄] まで 1 ずつ増やす) に、aの要素数 − 1、aの要素数、aの要素数 + 1 が並んでいたとします。1周目はどれも同じ動きなので区別できません。差が出るのは最後の周です。要素数3の配列で確かめると、− 1 は a[3] を足さずに終わり、+ 1 は存在しない a[4] を参照します。残るのは aの要素数 です。

境界で確かめるのは、選択肢の違いがたいてい境界にしか現れないからです。< と ≦、mid と mid + 1、i と i − 1 は、繰り返しの途中ではどちらも同じように動き、最初か最後の1周でだけ結果が分かれます。

1行ずつ動かして確かめるツール

トレース表を自分で書いたら、答え合わせをしたくなります。このサイトには、プログラムの動きを目で確かめるツールがあります。

  • プログラムのなぞり書き:プログラムを1行ずつ実行し、変数の値と出力の変化を表示します。上の切り替えで「擬似言語(基本情報)」を選ぶと、擬似言語の書き方で動かせます。関数を呼ぶたびに呼び出しの段が積み重なる様子も見えます。前の節の型ごとのリンクから、同じ型の例題を開けます。この記事のコードを貼り付けて動かすときは、最初の ○ より前の行に、呼び出す文(例:出力する(gcd(84, 36)))を書き足します。
  • 可視化スタディ(ソート):バブル・挿入・選択・マージ・クイックの各ソートで、配列が並び替わる様子をコマ送りで見られます。同じシリーズに探索と再帰もあります。
  • てじゅんカード:処理の手順を書いたカードを正しい順に並べ替えます。代入の順番を入れ替えると結果が変わる、という互除法や交換法の注意点を、手を動かして確かめられます。

ツールで動かすのは、自分のトレース表を書いたあとにします。先に動かしてしまうと、表を書く練習になりません。合わなかったときは、どの行で値がずれたかをツールの表示と見比べると、自分がどこで読み違えたかが分かります。

練習問題

この記事の内容から作ったオリジナルの問題です。配列の要素番号は、どの問題も1から始まります。トレース表を書いてから選んでください。選ぶとその場で正誤と解説が出ます。最初に選んだ答えで採点し、最後に正答数を表示します。

  1. 問1f(6) を呼び出したときの戻り値はどれか。

    ○整数型: f(整数型: n)  整数型: c  c ← 0  while (n > 1)    if (n mod 2 = 0)      n ← n ÷ 2    else      n ← 3 × n + 1    endif    c ← c + 1  endwhile  return c
    答えと解説を見る

    答え:8。n は 6→3→10→5→16→8→4→2→1 と変わり、矢印の数だけ c が増えるので8です。n が1になった時点で while の条件 n > 1 が偽になり、そこで止まります。

  2. 問2次の代入文を実行したあとの x の値はどれか。

    x ← 3 + 17 mod 5
    答えと解説を見る

    答え:5。mod は + より優先度が高いので、先に 17 mod 5 = 2 を計算し、3 + 2 = 5 です。左から順に (3 + 17) mod 5 と計算すると0になります。

  3. 問3g(12) を呼び出したときの戻り値はどれか。

    ○整数型: g(整数型: x)  整数型: y  y ← 0  if (x > 10)    y ← y + 1  elseif (x > 5)    y ← y + 10  else    y ← y + 100  endif  if (x mod 2 = 0)    y ← y + 1000  endif  return y
    答えと解説を見る

    答え:1001。12 > 10 が真なので y は1になり、elseif の 12 > 5 は評価しません。最初に真になった条件の処理だけを実行するからです。次の if は別の文なので評価され、12 mod 2 = 0 から1000を足して1001です。

  4. 問4digits(0) を呼び出したときの戻り値はどれか。

    ○整数型: digits(整数型: n)  整数型: c  c ← 0  do    c ← c + 1    n ← n ÷ 10 の商  while (n > 0)  return c
    答えと解説を見る

    答え:1。do 〜 while は後判定なので、条件を調べる前に処理を1回実行し、c は1になります。そのあと n > 0 が偽なので止まります。while (n > 0) 〜 endwhile の前判定で書くと、1回も実行せずに0を返します。0も1桁の数なので、桁数を数えるなら後判定が合っています。

  5. 問5関数 maxIndex は、配列 a の最大値が入っている要素番号を返す。最大値が複数あるときは、そのうち最も小さい要素番号を返す。空欄アに入れる字句はどれか。配列の要素番号は1から始まる。

    ○整数型: maxIndex(整数型の配列: a)  整数型: k, i  k ← 1  for (i を 2 から aの要素数 まで 1 ずつ増やす)    if (    ア    )      k ← i    endif  endfor  return k
    答えと解説を見る

    答え:a[i] > a[k]。k は「いままでの最大値の要素番号」なので、比べる相手は k ではなく a[k] です。a = {4, 9, 2, 9, 1} で確かめると、a[i] > a[k] は2を返します。≧ にすると、同じ9が出た4番で k が置き換わり、4を返してしまいます。

  6. 問6関数 binSearch に、a = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91} と x = 23 を渡した。値を返すまでに、mid ← (low + high) ÷ 2 の商 は何回実行されるか。配列の要素番号は1から始まる。

    ○整数型: binSearch(整数型の配列: a, 整数型: x)  整数型: low, high, mid  low ← 1  high ← aの要素数  while (low ≦ high)    mid ← (low + high) ÷ 2 の商    if (a[mid] = x)      return mid    elseif (a[mid] < x)      low ← mid + 1    else      high ← mid − 1    endif  endwhile  return −1
    答えと解説を見る

    答え:3回。1回目は low=1, high=10 で mid=5、a[5]=16 は23より小さいので low=6。2回目は mid=8、a[8]=56 は大きいので high=7。3回目は mid=6 で a[6]=23 と一致し、6を返します。

  7. 問7問6の binSearch で、low ← mid + 1 の行を low ← mid に書き換えた。このとき起こることとして正しいものはどれか。

    答えと解説を見る

    答え:x によっては、while の繰り返しが終わらなくなる。問6の配列で x=23 を探すと、low=5, high=6 になったところで mid=5、a[5]=16 は23より小さいので low ← 5 となり、low も high も変わりません。同じ状態が続くので終わりません。mid は調べ終わった位置なので、次の範囲から外す +1 が要ります。

  8. 問8次の手続で、aの要素数が5のとき、if の条件 a[j] > a[j + 1] が評価される回数はどれか。

    ○sort(整数型の配列: a)  整数型: n, i, j, tmp  n ← aの要素数  for (i を n から 2 まで 1 ずつ減らす)    for (j を 1 から i − 1 まで 1 ずつ増やす)      if (a[j] > a[j + 1])        tmp ← a[j]        a[j] ← a[j + 1]        a[j + 1] ← tmp      endif    endfor  endfor
    答えと解説を見る

    答え:10回。外側の i が5, 4, 3, 2 と変わるたびに、内側の j は 1 から i − 1 まで動くので、4+3+2+1=10回です。配列の中身には関係なく、交換するかどうかだけが変わります。要素数 n なら n(n − 1)/2 回です。

  9. 問9gcd(195, 75) を呼び出した。while の中の処理を繰り返す回数と、戻り値の組はどれか。

    ○整数型: gcd(整数型: m, 整数型: n)  整数型: r  while (n ≠ 0)    r ← m mod n    m ← n    n ← r  endwhile  return m
    答えと解説を見る

    答え:4回、15。r は 195 mod 75=45、75 mod 45=30、45 mod 30=15、30 mod 15=0 と4回計算します。4回目のあと n が0になって止まり、そのときの m=15 を返します。n ではなく m を返す点に注意します。

  10. 問10h(4721) を呼び出したときの戻り値はどれか。

    ○整数型: h(整数型: n)  if (n = 0)    return 0  endif  return n mod 10 + h(n ÷ 10 の商)
    答えと解説を見る

    答え:14。h(4721) は 1 + h(472)、h(472) は 2 + h(47) と、一の位を取り出しながら呼び出しを重ね、h(0) が0を返したところから戻りながら足します。0、4、11、13、14 の順に戻り値が決まり、各位の数の和14になります。