The binary interpretation of bits is only one possible ordering of the possible states in an n-bit register. A gray code is another interpretation where adjacent numbers vary in only one bit. wikipedia

The important idea is that we can assign meaning to bit patterns. See also Complement Representation

We can use the binary representation of numbers to compute a maximal sequence of bit patterns where only one bit changes between each element.

We begin with helper functions to print objects and compute single bit constants.

p = (val) -> console.log JSON.stringify val bit = (num) -> Math.pow 2, num

We'll set up our computation for a given number of bits. We'll keep lists of used and unused values.

bits = 6 used = [last = 0] unused = [1..(bit(bits)-1)]

Next will choose a number from unused and add it to used. We search unused choices for a possible choice made by flipping progressively larger bits.

next = -> for b in [0..bits-1] n = last ^ bit(b) i = unused.indexOf n if i>= 0 unused.splice i, 1 used.push last = n return true return false

We'll keep working until we can't continue.

'work' while next()

[ 0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8, 24, 25, 27, 26, 30, 31, 29, 28, 20, 21, 23, 22, 18, 19, 17, 16, 48, 49, 51, 50, 54, 55, 53, 52, 60, 61, 63, 62, 58, 59, 57, 56, 40, 41, 43, 42, 46, 47, 45, 44, 36, 37, 39, 38, 34, 35, 33, 32 ]

Pseudorandom sequences often go through most possible states of a counter. See Random Hello World.