エンジニアはこの言語をたぶん見たことがない
2025 年から共通テストに「情報I」が入り、国立大の受験者は原則としてこれを受けます。令和 8 年度(2026 年 1 月)の受験者は 305,202 人。基本情報技術者試験の年間受験者数のおよそ 2 倍が、1 月中旬の一発勝負で受けています。平均点は 56.69 点で、前年の約 70 点から大幅に難化しました。
その第 3 問には、プログラムを読ませる問題が出ます。使われるのは 特定の名前を持たない「共通テスト用プログラム表記」 という言語です。
擬似言語なので雑な言語だろう、と思って実物を読み始めたのですが、言語処理系を書く側の人間にとって、これは相当に変わった設計でした。この記事は受験対策ではなく、この言語を「言語」として読んだときに何が面白かったかの話です。
読んだのは、大学入試センターが公開している試作問題と、令和 7・8 年度の本試験・追試験。合計 10 本、約 100 行のプログラムです。
1. 確定した仕様書が存在しない
まずこれが最大の特徴です。
紛らわしいのですが、大学入試センターには DNCL(共通テスト手順記述標準言語) という別の言語があり、こちらには 11 ページの仕様書 PDF が存在します。ただし DNCL が使われるのは「情報関係基礎」という別科目で、情報I のプログラム表記とは別物です。世間では両方まとめて DNCL と呼ばれがちですが、書き方はかなり違います。
では情報I 側の仕様はどこにあるかというと、「令和 7 年度試験の問題作成の方向性、試作問題等」という資料の中に例示があるだけです。BNF もキーワード一覧も演算子の優先順位表もありません。しかもそこには、こう書かれています。
問題文中では簡潔にするため異なる形式を使うことがある
言語の定義文書が「この通りに書くとは限らない」と宣言している。処理系を書く立場からすると、これは相当に効きます。準拠すべき対象が存在しないからです。
結果として、この言語について観測可能な仕様は過去に出題された実物のコーパスだけになります。10 本・約 100 行が、公式に確認できる記法のすべてです。
2. 本試験だけを読むと、記法を取りこぼす
コーパスが仕様である言語では、コーパスの取り方の偏りが、そのまま仕様の誤りになります。これを実際に踏みかけました。
最初は本試験 2 回分だけを資料にしていました。そこには等価比較の演算子が一度も現れません。条件分岐は登場するのですが、たまたま大小比較(< や <=)ばかりだったのです。
追試験 2 回を資料に加えたところ、そこで初めて出てきました。
もし Shurui[i] == 1 ならば:
代入が =、等価比較が ==。C 系と同じ区別です。本試験だけを見て「代入も比較も = だろう」と決め打っていたら、教材の問題を全部まちがった記法で作るところでした。
同じことが そうでなければ:(else)でも起きています。これも本試験 2 回には出現せず、追試験で初めて確認できました。逆に そうでなくもし にあたる else if は、5 回分すべてで一度も出てきません。
「未出現」は「存在しない」ではありません。あくまで「確認できていない」です。仕様書がある言語ならこれは単なる調査不足ですが、この言語では未出現と非存在を区別する方法が原理的にない。ここが気持ち悪くもあり、面白くもあるところです。
3. 配列の添字の基点が、言語ではなく問題文で決まる
いちばん驚いたのがこれです。
配列の添字が 0 始まりか 1 始まりかは、言語では決まっていません。出題ごとに問題文で宣言されます。
なお,配列の添字は 0 から始まるものとする
この配列の添字(1 から始まる。)
実際に確認した 5 回分はこうでした。
| 回 | 添字の基点 |
|---|---|
| 試作問題 | 0 |
| 令和 7 年度 本試験 | 1 |
| 令和 7 年度 追試験 | 1 |
| 令和 8 年度 本試験 | 1 |
| 令和 8 年度 追試験 | 0 |
同じ年度の本試験と追試験で違う。これは事故ではなく意図的な設計で、DNCL の仕様書のほうにはこう明記されています。
添字の値は 0 以上の整数ですが、問題によっては 1 以上のみを扱います
つまり出題側は、添字の基点を言語仕様として固定せず、出題ごとの束縛にすることを公式に認めている。エンジニアの語彙で言えば、言語のパラメータを実装や実行時ではなく問題文で束縛しているわけです。
処理系を書くときにこれは効きます。私は結局、実行オプションの型をこうしました。
export interface Joho1Options {
/**
* 添字の基点。既定値を置かないのは意図的。
* 基点は問題ごとに宣言されるものなので、呼び出し側が必ず選ぶ。
*/
indexBase: 0 | 1;
}
indexBase = 1 をデフォルトにしたくなるのですが、デフォルトを置いた瞬間に嘘になります。基点を宣言し忘れたコードは、この言語では「1 始まり」ではなく「未定義」が正しい。省略可能にしない、という設計判断のほうが仕様に忠実でした。
同時に、教材側でも「情報I の配列は 1 始まり」と書いてはいけないことになります。多数決で書くと 5 回中 3 回は当たりますが、当たらなかった年の受験者が事故ります。
4. 標準ライブラリを持たない
このプログラムには関数呼び出しが出てきます。
kyakusu = 要素数(Touchaku)
Kaishi[i] = 最大値(Touchaku[i], Shuryou[i - 1])
要素数 や 最大値 は組み込み関数だろう、と思うところです。違いました。これらは毎回、問題文の**【関数の説明】**というボックスの中で、その場で日本語の散文として定義されています。「引数として配列が与えられ、その配列の要素数を返す」という調子で。
回をまたいで固定の組み込み関数セットは存在しません。ある回に出た 枚数(金額) のような関数は、その回のためだけに定義されたものです。
さらに、関数を定義する構文は 5 回とも一度も出現していません。定義は常に散文で与えられ、コードの中では呼ぶだけ。つまりこの言語には、利用者が書ける関数定義の記法が事実上ない(少なくとも観測されていない)。
依存をすべて外から注入する形になっていて、言語としては極端に小さい。受験者に求められているのは「組み込み関数を暗記していること」ではなく、その場で与えられた仕様を読んで使うことです。これは言語の学習というより、仕様書を読む能力を問うている。処理系を作る側も、関数は言語に組み込むのではなく問題ごとに注入する形が正解になります。
5. 論理演算子は英語なのに、毎回説明が付く
条件繰り返しはこう書きます。
(taiken <= 15) and (saichou < 10) の間繰り返す:
制御構造は「〜の間繰り返す」と日本語なのに、論理演算子は and / or と英語です。DNCL のほうは かつ / または / でない と日本語で統一されているので、ここは明確に別物です。
面白いのはその先で、これが出題される回では毎回、問題文に説明が付きます。
「and」は「かつ」を意味する論理演算子であり
エンジニアからすると and に説明が要るのかと思うのですが、これは**出題側が「受験者がこの演算子を知っている前提を置いていない」**ということです。1 行の記法にすら前提を置かない。ちなみに not は 5 回とも出現していません。
同じ思想は演算子にも出ていて、整数の商が ÷、剰余が % で書かれます。/ でも % でもなく、算数で習う記号のままです。
6. 「書かれることのない言語」として設計されている
ブロック構造の表し方が独特です。インデントではありません。以下は令和 8 年度本試験の第 3 問から、記法が分かる部分だけを抜粋したものです(行番号は連番に振り直しています)。
(01) Touchaku = [0, 3, 4, 10, 11, 12]
(02) kyakusu = 要素数(Touchaku)
(03) taiken を 1 から 15 まで 1 ずつ増やしながら繰り返す:
(04) │ Kaishi = [0, 0, 0, 0, 0, 0]
(05) │ i を 2 から kyakusu まで 1 ずつ増やしながら繰り返す:
(06) │ │ Kaishi[i] = 最大値(Touchaku[i], Shuryou[i - 1])
(07) │ └ Shuryou[i] = Kaishi[i] + taiken
行頭に (01) の行番号、ブロックの深さは縦罫線 │ の本数、ブロックの最終行は └。コロンで開いて、罫線で閉じる。閉じキーワード(endif のようなもの)はありません。
最初は冗長に見えたのですが、この言語が置かれている状況を考えると理にかなっています。
- 読者は紙面でこれを読む。指で追う
- 「(06) 行目の処理は何回実行されるか」という設問が成立する必要がある
- ブロックの最終行がどこかを、目で即座に確定できる必要がある
そして決定的なのは、受験者はこの言語を書かないということです。80 分の試験で読んで、穴埋めをするだけ。エディタも処理系も存在しません。
我々が普段さわる言語は「書くため」に設計されていて、読みやすさはその副産物です。この言語は逆で、読むためだけに設計されている。パースのしやすさや記述量は最適化の対象になっていません。罫線でブロックを描くのは、書く側にとっては最悪の記法ですが、読む側にとっては最良に近い。
ちなみに実装では、入力はインデントで受け取り、表示だけ行番号と罫線に変換しています。受験者が最初にやる操作は問題冊子からのコピペなので、行番号と罫線が付いたまま貼られたコードを、罫線の本数を字下げに変換して受け取る正規化も入れました。この辺の実装の話は長くなるので別に書きます。
7. 全角と半角が揺れている
細かい点ですが、記法が固まっていないことの証拠として面白いところです。
試作問題では比較演算子が全角の < で書かれていました。本試験 2 回はどちらも半角の < <= です。一方で、整数の商 ÷ と剰余 % は全角のまま。
仕様書がないので「どちらが正しい」という判定ができません。本試験 2 回が半角なので教材は半角を正として書き、処理系の字句解析では両方受け付ける、という妥協にしました。入力の受け口は広く、表示は本試験に合わせるという方針です。
これは「雑な言語」なのか
ここまで書くと欠陥の列挙のように見えますが、読み終えた印象は逆でした。
プログラミング言語の仕様書は、曖昧さを消すために書かれます。実装者が別々に読んでも同じ処理系ができることが目的です。この言語には実装者がいません。試験問題を作る人と、それを 80 分読む人しかいない。
その状況で曖昧さをどう消しているかというと、曖昧になりうる箇所を、言語仕様ではなく問題文に移しているわけです。
- 添字の基点 → 問題文で宣言する
- 使える関数とその意味 → 問題文の【関数の説明】で与える
- 演算子の意味 → 問題文で毎回説明する
言語の外側に仕様を置く設計です。エンジニアが業務でこれをやったら事故ですが、「その回のその問題を、全員が同じように読める」ことだけが要件なら、これは十分に合理的です。むしろ、受験者が言語仕様を暗記していることに依存しない設計になっている。
一方で、この設計は独学者に厳しいとも思いました。仕様書がないので「この言語を学ぶ」という行為が成立せず、過去問の実物を読む以外に近づく方法がありません。この記事のために私がやったこと(実物を 10 本集めて記法を突き合わせる)は、本来は受験生がやる作業ではないはずです。
動かしてみたい人へ
読んでいるうちに、これは実際に動かしたほうが早いと思ったので、ブラウザ上で 1 行ずつ実行できるものを作りました。変数の値が毎ステップ更新されるので、繰り返しの中で配列がどう変わるかを目で追えます。
この記事で触れた点は、それぞれページにしてあります。
- 添字の基点が 0 か 1 かで何が変わるか — シミュレーターは基点を切り替えられます
- 問題文で与えられる外部関数の読み方
- DNCL と共通テスト用プログラム表記は何が違うのか
- 同じ処理をプログラム表記と Python で並べる
一次資料はこちらです。実物を読むのがいちばん早いです。
- 共通テスト手順記述標準言語(DNCL)の説明(PDF) — こちらは情報関係基礎用。情報I とは別物ですが、添字の基点についての記述はここにあります
- 令和 7 年度試験の問題作成の方向性、試作問題等 — 大学入試センター
- DNCL?プログラム表記? — 奥村晴彦 — 名称の混乱について整理されています
おわりに
仕様書のない言語を、実物 100 行から読み解く作業は、思っていたよりリバースエンジニアリングそのものでした。「本試験だけ見ていたら == を取りこぼしていた」というのが個人的にいちばん怖かった話で、コーパスが仕様である以上、サンプリングの偏りが仕様の誤りに直結します。
30 万人が毎年読まされている言語なのに、エンジニア側からはほとんど話題にならない領域です。実物は公開されているので、興味があれば第 3 問だけでも眺めてみると面白いと思います。