A (binary) Gray code is a sequence of bit strings that run through all $2^n$ strings in $\{0,1\}^n$, and where successive strings differ by only one bit. Here's a $3$-bit Gray code, where the strings are written as columns:
$00001111$
$00111100$
$01100110$
A single-track Gray code has the property that each row is identical up to offsets (i.e., cyclical shifts). It is impossible for such a code to run through all $2^n$ strings, so this condition is relaxed. Here's a $5$-bit single-track Gray code, with red zeroes showing the offsets:
$\color{red}00000001110001111111$
$1111\color{red}0000000111000111$
$01111111\color{red}000000011100$
$110001111111\color{red}00000001$
$0001110001111111\color{red}0000$
Note that the above code is not maximal in the sense that it only runs through $20$ words, while it is possible for a $5$-bit single-track Gray code to run through up to $30$ words. But that's fine. Also note that the offsets are evenly spaced. That's not strictly necessary.
Question: I am looking for ternary (or higher $k$-ary) single-track Gray codes for small values of $n$ (say $3 \leq n \leq 6$). In other words, the codes would run through (some of) the strings in $\{0,1,2\}^n$ without repeats, where successive strings differ in one place. The codes don't need to be maximal, and the offsets don't need to be evenly spaced. Any ideas?
Joriki's code, for posterity:
import java.util.Random;
import java.util.Stack;
public class Question1676642 {
final static int k = 3;
final static int n = 6;
public static void main (String [] args) {
int record = 0;
Random random = new Random ();
Stack<int []> words = new Stack<int[]> ();
outer:
for (;;) {
words.clear ();
int [] first = null;
int [] next = null;
int failCount = 0;
for (;;) {
if (words.isEmpty ()) {
first = next = new int [n];
for (int i = 0;i < n;i++)
next [i] = random.nextInt (k);
}
else {
next = words.get (words.size () - 1).clone ();
int index = random.nextInt (n);
int value = random.nextInt (k - 1) + 1;
next [index] += value;
next [index] %= k;
}
words.push (next);
boolean valid = true;
for (int [] word : words)
for (int i = 0;i < n;i++)
if (word != next || i != 0) {
boolean same = true;
for (int j = 0;j < n;j++)
same &= next [j] == word [(j + i) % n];
valid &= !same;
}
if (valid) {
failCount = 0;
if (words.size () > record)
for (int d = -1;d <= 1;d += 2) {
int diffs = 0;
for (int i = 0;i < n;i++)
if (first [i] != next [(i + d + n) % n])
diffs++;
if (diffs == 1) {
System.out.println ("words: " + words.size ());
for (int i = 0;i < n;i++) {
System.out.print (" ");
for (int j = 0;j < words.size ();j++)
System.out.print (words.get (j) [i]);
System.out.println ();
}
System.out.println ();
record = words.size ();
}
}
}
else {
words.pop ();
if (++failCount == 100)
continue outer;
}
}
}
}
}
– joriki Mar 06 '16 at 21:09000000011100011111110000000222000222222211111112221112222222
000111000111111100000002220002222222111111122211122222220000
110001111111000000022200022222221111111222111222222200000001
011111110000000222000222222211111112221112222222000000011100
111100000002220002222222111111122211122222220000000111000111