An ordering of all bit strings where consecutive strings differ in exactly one bit. It’s a Hamiltonian cycle of the hypercube, and it lets you enumerate subsets with one insertion or deletion per step.
Reflected binary code
unsigned gray(unsigned i) { return i ^ (i >> 1); }
unsigned grayInverse(unsigned g) { for (unsigned s = g >> 1; s; s >>= 1) g ^= s; return g; }
// or in O(log w): g ^= g >> 1; g ^= g >> 2; g ^= g >> 4; g ^= g >> 8; g ^= g >> 16;- and differ in bit .
- The sequence is cyclic: differs from in one bit.
- parity of the step count , since each step flips exactly one bit.
- Tower of Hanoi: move moves disk , the same bit that changes in the Gray code.
Proof: is a bijection with the one-bit-step and decoding properties
One-bit step. Let . Binary increment gives: for , bit of is and of is ; bit of is and of is ; for , the two agree. Bit of is . For : both and agree between and (either both above , or where bit is also unchanged by the increment), so . For : gives , and gives — equal. For (when ): gives , and gives — equal. At : gives , and gives — these differ. So has exactly bit set. Bijection. has a two-sided inverse: the loop
for s=g>>1; s; s>>=1: g^=srecovers top bit down, since (from ) and by the time bit is XORed,scarries exactly the already-recovered bit of shifted into position. A function on a finite set with a two-sided inverse is a bijection, hence a permutation of ; combined with the one-bit-step property, is a Hamiltonian path on the hypercube . Cyclic. , a single bit, so the last and first codes also differ in exactly one bit, closing the path into a Hamiltonian cycle.Tested:
gray/grayInverse/the unrolled inverse all checked against a full enumeration of — range, bijectivity (no collisions), round-trip inverse, single-bit adjacency with the predicted position, and the cyclic wraparound.
Enumerating subsets with updates
for (unsigned i = 0; i < 1u << n; i++) {
if (i) { int b = __builtin_ctz(i); (gray(i) >> b & 1) ? add(b) : remove(b); }
process(gray(i));
}That’s single-element updates instead of . Useful when inserting or removing one element is expensive: maintaining a matrix product, a determinant via rank-one updates, a convex hull, or computing the permanent with Ryser’s formula in (Permanent).
Variants and facts
- -ary reflected Gray code: consecutive strings differ by in one digit. Generate by reflecting digit order like the binary case.
- Gray code over a subset lattice of fixed size (revolving door / combinations differing by one swap): enumerate all -subsets with one element swapped out and one in per step.
- Hamiltonian cycle on with a prescribed start: XOR every code with the start.
- Hamiltonian path in a hypercube between two vertices: exists iff they have different parity (bipartite), and a recursive construction splits on a coordinate where they differ.
- Minimum number of single-bit flips to visit all states: , attained by Gray code.
- Balanced Gray code: a variant where every bit position changes roughly the same number of times across the whole cycle, rather than the reflected code’s heavy skew toward the low bits. Monotone Gray code: one where the sequence of changed-bit positions follows a monotone pattern. Snake-in-the-box: the longest induced path in a hypercube (no two non-consecutive visited vertices adjacent) — an open combinatorial problem in general, unlike the Hamiltonian-cycle question Gray code answers exactly.
- Outside CP: rotary encoders and ADCs use Gray code so a reading caught mid-transition is off by at most one step, instead of the arbitrary garbage ordinary binary gives on a multi-bit flip (e.g. ); Karnaugh maps label rows/columns in Gray code so adjacent cells differ in one variable, which is what makes the visual minimisation of boolean functions work.
Proof: the lower bound, and the parity condition for a two-endpoint Hamiltonian path
Lower bound. Visiting all distinct states one flip at a time is a walk through vertices, which uses exactly (number of vertices) 1 edges if no vertex repeats; fewer than flips can touch at most new states beyond the start, i.e. at most states total only if every flip reaches a genuinely new state, so is also necessary, not just sufficient. The Gray code achieves it exactly (it’s a Hamiltonian path, proved above), so is tight. Parity. The hypercube is bipartite by , since every edge flips one bit and so changes parity by exactly one step. A path alternates between the two parity classes, so a Hamiltonian path from to visits vertices alternating parity starting at ; this forces . For , is odd, so is necessary. (Sufficiency is the standard recursive construction: split into two copies by the coordinate where differ, Hamilton-path each half using the inductive hypothesis on the smaller cube, and join them across that one differing coordinate.)
- De Bruijn sequences are the cyclic analogue for windows rather than whole strings (Euler Tours).