グレイコード

目次

問題設定

このような問題を考えてみる。

あなたの前にはn個のスイッチがある。スイッチはONまたはOFFの状態を取る。最初はすべてOFFとなっている。

このスイッチは金庫の鍵となっていて、これらのスイッチがある特定の組み合わせの状態になったときだけ解錠される。

たとえば、(OFF-ON-ON-OFF-ON)のときだけ金庫は開く。それ以外では金庫は閉じている。といった具合である。

しかし、あなたは正解の組み合わせを忘れてしまっている。

金庫を開けるためにあなたはどのように、スイッチの組み合わせを試していくか?

最も素直な解き方は、全探索(ブルートフォース)である。

つまり、スイッチ列の状態を2nの数値にコーディングし、0から2n1までのスイッチの状態を試していくことである。

たとえば、n=3の場合、次のように試していくことになる。

コード2進数スイッチの状態
0000OFF-OFF-OFF
1001OFF-OFF-ON
2010OFF-ON-OFF
3011OFF-ON-ON
4100ON-OFF-OFF
5101ON-OFF-ON
6110ON-ON-OFF
7111ON-ON-ON

これは、良い方法であるが、スイッチの切替の回数が少し多いのが難点である。

たとえば、0 -> 1の切り替えは右のスイッチを押すだけでよいが、1 -> 2の切り替えでは真ん中と右のスイッチを押さなければならない。 この方法では、スイッチを押す回数は全部で11回となる。

少し疲れるので、「もっと少なく済ませることはできないだろうか?」というのが今回の問題である。

n=2のとき

最初の0は固定するとして、残りの2n1の数値を並べる方法は(2n1)!通りある。

これをすべて調べて、スイッチ回数が最小のパターンを調べるのは大変であるが、n=2の時なら6通りに過ぎないので、すべてを調べることができる。

(1) 0,1,2,3

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
101OFF-ON1
210ON-OFF2
311ON-ON1

スイッチの回数は4回である。

(2) 0,1,3,2

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
101OFF-ON1
311ON-ON1
210ON-OFF1

スイッチの回数は3回である。

(3) 0,2,1,3

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
210ON-OFF1
101OFF-ON2
311ON-ON1

スイッチの回数は4回である。

(4) 0,2,3,1

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
210ON-OFF1
311ON-ON1
101OFF-ON1

スイッチの回数は3回である。

(5) 0,3,1,2

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
311ON-ON2
101OFF-ON1
210ON-OFF2

スイッチの回数は5回である。

(6) 0,3,2,1

コード2進数スイッチの状態前回から変化したスイッチの数
000OFF-OFF-
311ON-ON2
210ON-OFF1
101OFF-ON2

スイッチの回数は5回である。

結論

n=2の場合、{00,01,11,10}もしくは{00,10,11,01}が最小の探索手順である。

n=3のとき

次にn=3のときを考える。今度は全部調べると7!=5040通りであって大変なので、最初から最小手数7回を目標にする。

0から2n1までの各数値を頂点として、「ビットが1つだけ異なる」という関係を持つ頂点を結ぶと、次の図の左のような立方体のグラフが得られる。

このグラフの頂点を1回ずつ通る経路を求めると、これが求めたい探索手順となっているので、これを調べる。

本質的に異なる探索手順は図の右側に示した3つの手順だけである。

なお、一般に、グラフの頂点を1回ずつ通る経路はハミルトン路(Hamiltonian path)と呼ばれている。

対称性を考慮すると、このような経路は000スタートのものに限っても332=18個ある (最初の行き先の頂点の選び方で3通り、次の行き先の頂点の選び方で2通りある)。

一般のn

n=3のときの考え方によると、この問題は

n次元超立方体グラフ(hypercube graph)のある頂点を出発点とするハミルトン路を求める問題

と解釈することができる。n=22通り、n=318通りであるから、こういったハミルトン路はかなりありそうである。

そのうちのなにか一つをアルゴリズム的に構成することはできないだろうか?

具体的な発想としてはn1次元超立方体グラフのハミルトン路がわかっているのであれば、それを利用してn次元超立方体のハミルトン路を構成することはできないだろうか。

色々考えてみると、次のような方法が考えられる。

(1) まず、最上位ビット0の状態で、下位n1ビットについて既知の系列を適用する。

(2) 既知の系列の最後まで来たら、最上位ビットだけを1に変更する。

(3) 次に下位n1ビットについて、(1)で使用した系列を逆にした系列を適用する。

たとえば、n=1のときの系列{0,1}を出発点として、n=2,3,4について、このアルゴリズムで構成される系列は次のようなものである。

  • n=2のとき、{00,01,11,10}
  • n=3のとき、{000,001,011,010,110,111,101,100}
  • n=4のとき、{0000,0001,0011,0010,0110,0111,0101,0100,1100,1101,1111,1110,1010,1011,1001,1000}

この系列は無限に作ることができる。

この系列は、一般にグレイコード(Gray code)と呼ばれている有名な系列である。

グレイコードの数

「グレイコード」という言葉は先に示したアルゴリズムで構成される具体的な系列を指すことが多いが、隣り合うビットが1つだけ異なるような性質を持つ系列を一般に指すこともある。

これは、先に示したように、 n次元超立方体グラフ(hypercube graph)のある頂点を出発点とするハミルトン路と同一視できるものである。

このグレイコードの数はn=1のときは1つ、n=2のときは2つ、n=3のときは18個まで求めたが、この後どのように増えるかというと次のようになる。

  • n=4のとき、5,712
  • n=5のとき、5,859,364,320

非常に急激に増加する。

この数列は、OEISのA003043にリストされている。