はじめに
この記事は 共通テスト手順記述標準言語 (DNCL) Advent Calendar 2025 の10日目の記事です。
DNCLでカウントソートを書いてみたので、共テ風に書きます。
カウントソートとは
Dさんが所属する40人のクラスには10人1組の班がある。班長は毎日、班員のノートを回収し、出席番号順に並び変えた上で担任の先生に提出しなければならない。班長であるDさんは班員のノートをすべて回収した。ノートを出席番号順に並び替えようとしたところで、Dさんは情報の授業で習った カウントソート を思い出したので、これを用いて10冊のノートを並び替えようとした。
まず初めにDさんは、机の上のどこに何番のノートを置くのかを1番から40番について図1のように決めた。これは、並べるノートは10冊だが10人の出席番号がわからないため、何番であっても並べられるようにするものである。

次にDさんは、集めたノートを上から手に取り、図2のようにノートに書かれた出席番号を見て対応する場所にノートを置いた。

Dさんは最後に、1番の場所から順にノートが置いてあるかを確認し、もしノートがあればかご入れていった。
こうしてノートの並び替えを終えたDさんは先生に班員のノートを提出し家路についた。
カウントソートを書いてみる
次の日、班長であるDさんは昨日と同じようにノートを回収し並べ替えをしていた。Dさんは毎日並べ替える方法を考えるのが面倒だと感じ、ノートを並び替えるアルゴリズムを作成しようと考えた。
各出席番号の位置にノートが置かれているかどうかを管理するために配列Tsukuenoueを用意する。この配列の添え字(1から始まる。)はクラスの出席番号であり、その要素は出席番号に対応する各位置に置かれたノートの冊数である。
例えば、図3の状況では、配列Tsukuenoueは図4のようになる。図3で2番と5番にノートがあるため、図4で要素Tsukuenoue[2]と要素Tsukuenoue[5]はともに1となる。また、3番の位置にはノートがないため、図4で要素Tsukuenoue[3]は0となる。さらに、図4で要素Tsukuenoue[27]は2なので、27番の人がノートを2冊提出したことがわかる。


この考え方に基づき、Dさんは配列Tsukuenoueと回収したノートの冊数が代入された変数satsusu、ノートに書かれている出席番号を要素にもつ配列Kaisyu(添字は1から始まる。)そしてクラスの人数が代入された変数ninzuを用いて、机の上の出席番号と対応した位置にノートを並べるアルゴリズムを作成した(ここでは、並べた数を記録することを並べるという)(図5)。
(01)Tsukuenoue = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
(02)Kaisyu = [34, 13, 8, 22, 33 ,12, 32, 29, 25, 6, 12]
(03)satsusu = 11
(04)ninzu = 40
(05)iを1からsatsusu + 1まで1ずつ増やしながら繰り返す:
(06)└ Tsukuenoue[Kaisyu[i]] = Tsukuenoue[Kaisyu[i]] + 1
仮に回収したノートの数が変わったとしても、配列Kaisyuと変数satsusuを適切に設定すれば、このアルゴリズムを用いることができる。12番と13番のノートがさらに1冊ずつ追加された場合、(02)行目を例えばKaisyu = [34, 13, 8, 22, 33 ,12, 32, 29, 25, 6, 12, 12, 13]に、(03)行目をsatsusu = 13に変更して図5のアルゴリズムを用いると、要素Tsukuenoue[12]は3となる。
次にDさんは、机の上に並べたノートを1番から順に確認し、もしノートがあればかごに入れていくアルゴリズムを作ることにした。
Dさんはかごの中にあるノートの出席番号を記録した配列Kagoを用意する。この配列の添字(1から始まる。)はかごの上から何冊目にあるかを表しており、その要素はノートに書かれた出席番号である。
例えば 要素Kago[1] = 6 であればかごの一番上には6番のノートがあることを表す。
Dさんは最初に0という要素をノートの冊数を表す変数satsusuだけもった配列Kagoを用いて、机の上のノートをかごに入れるアルゴリズムを作成した(図6)。
(01)Tsukuenoue = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
(02)Kaisyu = [34, 13, 8, 22, 33 ,12, 32, 29, 25, 6, 12]
(03)satsusu = 11
(04)ninzu = 40
(05)iを1からsatsusu + 1まで1ずつ増やしながら繰り返す:
(06)└ Tsukuenoue[Kaisyu[i]] = Tsukuenoue[Kaisyu[i]] + 1
(07)kago = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
(08)c = 1
(09)iを1からninzu + 1まで1ずつ増やしながら繰り返す:
(10)| もしTsukuenoue[i] > 0ならば:
(11)| | jを0からTsukuenoue[i]まで1ずつ増やしながら繰り返す:
(12)| | | Kago[c] = i
(13)└ └ └ c = c + 1
Dさんは図6のアルゴリズムを用いてノートを並べ替えた後、ノートを先生に提出し、家に帰った。
カウントソートの計算量
一昨日、昨日とノートをきちんと出席番号順に並べて先生に提出したDさんは、その腕を買われて学年職員室に提出される学年全員のノートを並べ替えるように言われた。実は、ノートをきちんと並べ替えて提出していたのはDさんのクラスのDさんの班だけだったのである。
ノートには組と出席番号のほかに、学籍番号が書かれている。先生から学年全員の300人分のノートを受け取ったDさんは昨日作ったのアルゴリズムを用いて学籍番号を基準に並べ替えようとした。
昨日のアルゴリズムはノートがN冊あるとき、ノートの山を上から下まで1周確認する間に山から机の上にN回移動させ、ノートを机の上からかごの中にN回移動させるため、およそ2N回ノートを移動させる必要がある。Dさんは2 * 300より600回移動させることを考え、すぐに終わると思った。
しかし、昨日はクラスメート40人分の出席番号に対応する位置を確保するだけでよかったので机の上で行うことができたが、300人分の学籍番号に対応する位置を机の上で確保することは困難である。悩んだ末、Dさんは教室の机を後ろに下げ、空いた床に300人分の位置を確保し、ノートを並び替えた。
並び替えを終えたDさんは、教室の机を元に戻し、300人分のノートを先生に提出した後、「筋トレした方がいいかな」と思いながら家に帰った。