A tiny Java library for generating Gray codes
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
This library is for generating Gray codes. A Gray code over $n$ bits is a list of $2^n$ different $n$-bit strings subject to the following constraint: two adjacent bit string differ in only one position. For example, the Gray code over four bits is
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000
Without further ado, let's proceed to code.
GrayCode.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class holds the Gray code.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCode
private final BitSet code;
private final int bits;
GrayCode(BitSet code, int bits)
this.code = code;
this.bits = bits;
public boolean isValid()
if (getNumberOfBits() == 0)
return code.length == 0;
int rowLength = getNumberOfBits();
BitSet previousRow = getRow(0);
for (int row = 1; row < getNumberOfRows(); row++)
BitSet currentRow = getRow(row);
if (getDifferenceCounts(previousRow, currentRow) != 1)
return false;
previousRow = currentRow;
return true;
public int getNumberOfBits()
return bits;
public int getNumberOfRows()
return this.code.length;
public BitSet getRow(int index)
BitSet bitSet = new BitSet(getNumberOfBits());
for (int i = 0; i < bits; ++i)
bitSet.set(i, code[index].get(i));
return bitSet;
public boolean readBit(int row, int column)
return code[row].get(column);
@Override
public String toString()
StringBuilder stringBuilder = new StringBuilder();
String rowSeparator = "";
for (int row = 0; row < code.length; ++row)
stringBuilder.append(rowSeparator);
rowSeparator = "n";
rowToBitString(stringBuilder, code[row]);
return stringBuilder.toString();
private void rowToBitString(StringBuilder stringBuilder, BitSet bitSet)
for (int i = 0; i != bits; ++i)
stringBuilder.append(bitSet.get(i) ? '1' : '0');
private int getDifferenceCounts(BitSet row1, BitSet row2)
int differenceCount = 0;
for (int i = 0; i < bits; ++i)
if (row1.get(i) != row2.get(i))
differenceCount++;
if (differenceCount == 2)
return differenceCount;
return differenceCount;
GrayCodeGenerator.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class provides a method for generating Gray code over particular number
* of bits.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public class GrayCodeGenerator
public static GrayCode generate(int bits)
checkBits(bits);
if (bits == 0)
return new GrayCode(new BitSet[0], 0);
BitSet bitSetArray = new BitSet[getNumberOfBitStrings(bits)];
for (int i = 0; i != bitSetArray.length; ++i)
bitSetArray[i] = new BitSet(bits);
bitSetArray[1].set(bits - 1);
for (int bitIndex = bits - 1, columnHeight = 2, width = 1;
bitIndex > 0;
bitIndex--, columnHeight <<= 1, ++width)
// Mirror down:
for (int row1 = columnHeight,
row2 = columnHeight - 1;
row1 < (columnHeight << 1);
row1++,
row2--)
for (int w = bits - 1; w > bitIndex - 1; w--)
bitSetArray[row1].set(w, bitSetArray[row2].get(w));
// Fill the prefix bits:
for (int row = columnHeight; row < (columnHeight << 1); ++row)
bitSetArray[row].set(bitIndex - 1);
return new GrayCode(bitSetArray, bits);
/**
* Returns the number of rows in the Gray code over @code bitsÃÂ bits.
*
* @param bits the number of bits.
* @return the number of rows in the resulting Gray code.
*/
private static int getNumberOfBitStrings(int bits)
return 1 << bits;
/**
* Checks that the number of bits is not negative.
*
* @param bits the number of bits to check.
*/
private static void checkBits(int bits)
if (bits < 0)
throw new IllegalArgumentException(
"Negative number of bits requested: " + bits);
GrayCodeDemo.java
package net.coderodde.graycode;
/**
* This class implements a sample Gray code demonstration.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCodeDemo
public static void main(String args)
GrayCode grayCode = GrayCodeGenerator.generate(4);
System.out.println(grayCode);
System.out.println("Valid Gray code: " + grayCode.isValid());
GrayCodeTest.java
package net.coderodde.graycode;
import java.util.BitSet;
import org.junit.Test;
import static org.junit.Assert.*;
public class GrayCodeTest
@Test
public void test()
GrayCode grayCode = GrayCodeGenerator.generate(2);
assertEquals(4, grayCode.getNumberOfRows());
assertEquals(2, grayCode.getNumberOfBits());
System.out.println(grayCode);
assertTrue(grayCode.isValid());
// Check first column:
assertFalse(grayCode.readBit(0, 0));
assertFalse(grayCode.readBit(1, 0));
assertTrue(grayCode.readBit(2, 0));
assertTrue(grayCode.readBit(3, 0));
// Check second column:
assertFalse(grayCode.readBit(0, 1));
assertTrue(grayCode.readBit(1, 1));
assertTrue(grayCode.readBit(2, 1));
assertFalse(grayCode.readBit(3, 1));
BitSet row1 = grayCode.getRow(1);
assertFalse(row1.get(0));
assertTrue(row1.get(1));
@Test
public void bruteForceTest()
for (int bits = 0; bits < 12; bits++)
assertTrue(GrayCodeGenerator.generate(bits).isValid());
Critique request
Please tell me anything that comes to mind. I am most interested in comments regarding the API design.
java algorithm unit-testing library
add a comment |Â
up vote
3
down vote
favorite
This library is for generating Gray codes. A Gray code over $n$ bits is a list of $2^n$ different $n$-bit strings subject to the following constraint: two adjacent bit string differ in only one position. For example, the Gray code over four bits is
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000
Without further ado, let's proceed to code.
GrayCode.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class holds the Gray code.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCode
private final BitSet code;
private final int bits;
GrayCode(BitSet code, int bits)
this.code = code;
this.bits = bits;
public boolean isValid()
if (getNumberOfBits() == 0)
return code.length == 0;
int rowLength = getNumberOfBits();
BitSet previousRow = getRow(0);
for (int row = 1; row < getNumberOfRows(); row++)
BitSet currentRow = getRow(row);
if (getDifferenceCounts(previousRow, currentRow) != 1)
return false;
previousRow = currentRow;
return true;
public int getNumberOfBits()
return bits;
public int getNumberOfRows()
return this.code.length;
public BitSet getRow(int index)
BitSet bitSet = new BitSet(getNumberOfBits());
for (int i = 0; i < bits; ++i)
bitSet.set(i, code[index].get(i));
return bitSet;
public boolean readBit(int row, int column)
return code[row].get(column);
@Override
public String toString()
StringBuilder stringBuilder = new StringBuilder();
String rowSeparator = "";
for (int row = 0; row < code.length; ++row)
stringBuilder.append(rowSeparator);
rowSeparator = "n";
rowToBitString(stringBuilder, code[row]);
return stringBuilder.toString();
private void rowToBitString(StringBuilder stringBuilder, BitSet bitSet)
for (int i = 0; i != bits; ++i)
stringBuilder.append(bitSet.get(i) ? '1' : '0');
private int getDifferenceCounts(BitSet row1, BitSet row2)
int differenceCount = 0;
for (int i = 0; i < bits; ++i)
if (row1.get(i) != row2.get(i))
differenceCount++;
if (differenceCount == 2)
return differenceCount;
return differenceCount;
GrayCodeGenerator.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class provides a method for generating Gray code over particular number
* of bits.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public class GrayCodeGenerator
public static GrayCode generate(int bits)
checkBits(bits);
if (bits == 0)
return new GrayCode(new BitSet[0], 0);
BitSet bitSetArray = new BitSet[getNumberOfBitStrings(bits)];
for (int i = 0; i != bitSetArray.length; ++i)
bitSetArray[i] = new BitSet(bits);
bitSetArray[1].set(bits - 1);
for (int bitIndex = bits - 1, columnHeight = 2, width = 1;
bitIndex > 0;
bitIndex--, columnHeight <<= 1, ++width)
// Mirror down:
for (int row1 = columnHeight,
row2 = columnHeight - 1;
row1 < (columnHeight << 1);
row1++,
row2--)
for (int w = bits - 1; w > bitIndex - 1; w--)
bitSetArray[row1].set(w, bitSetArray[row2].get(w));
// Fill the prefix bits:
for (int row = columnHeight; row < (columnHeight << 1); ++row)
bitSetArray[row].set(bitIndex - 1);
return new GrayCode(bitSetArray, bits);
/**
* Returns the number of rows in the Gray code over @code bitsÃÂ bits.
*
* @param bits the number of bits.
* @return the number of rows in the resulting Gray code.
*/
private static int getNumberOfBitStrings(int bits)
return 1 << bits;
/**
* Checks that the number of bits is not negative.
*
* @param bits the number of bits to check.
*/
private static void checkBits(int bits)
if (bits < 0)
throw new IllegalArgumentException(
"Negative number of bits requested: " + bits);
GrayCodeDemo.java
package net.coderodde.graycode;
/**
* This class implements a sample Gray code demonstration.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCodeDemo
public static void main(String args)
GrayCode grayCode = GrayCodeGenerator.generate(4);
System.out.println(grayCode);
System.out.println("Valid Gray code: " + grayCode.isValid());
GrayCodeTest.java
package net.coderodde.graycode;
import java.util.BitSet;
import org.junit.Test;
import static org.junit.Assert.*;
public class GrayCodeTest
@Test
public void test()
GrayCode grayCode = GrayCodeGenerator.generate(2);
assertEquals(4, grayCode.getNumberOfRows());
assertEquals(2, grayCode.getNumberOfBits());
System.out.println(grayCode);
assertTrue(grayCode.isValid());
// Check first column:
assertFalse(grayCode.readBit(0, 0));
assertFalse(grayCode.readBit(1, 0));
assertTrue(grayCode.readBit(2, 0));
assertTrue(grayCode.readBit(3, 0));
// Check second column:
assertFalse(grayCode.readBit(0, 1));
assertTrue(grayCode.readBit(1, 1));
assertTrue(grayCode.readBit(2, 1));
assertFalse(grayCode.readBit(3, 1));
BitSet row1 = grayCode.getRow(1);
assertFalse(row1.get(0));
assertTrue(row1.get(1));
@Test
public void bruteForceTest()
for (int bits = 0; bits < 12; bits++)
assertTrue(GrayCodeGenerator.generate(bits).isValid());
Critique request
Please tell me anything that comes to mind. I am most interested in comments regarding the API design.
java algorithm unit-testing library
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
This library is for generating Gray codes. A Gray code over $n$ bits is a list of $2^n$ different $n$-bit strings subject to the following constraint: two adjacent bit string differ in only one position. For example, the Gray code over four bits is
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000
Without further ado, let's proceed to code.
GrayCode.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class holds the Gray code.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCode
private final BitSet code;
private final int bits;
GrayCode(BitSet code, int bits)
this.code = code;
this.bits = bits;
public boolean isValid()
if (getNumberOfBits() == 0)
return code.length == 0;
int rowLength = getNumberOfBits();
BitSet previousRow = getRow(0);
for (int row = 1; row < getNumberOfRows(); row++)
BitSet currentRow = getRow(row);
if (getDifferenceCounts(previousRow, currentRow) != 1)
return false;
previousRow = currentRow;
return true;
public int getNumberOfBits()
return bits;
public int getNumberOfRows()
return this.code.length;
public BitSet getRow(int index)
BitSet bitSet = new BitSet(getNumberOfBits());
for (int i = 0; i < bits; ++i)
bitSet.set(i, code[index].get(i));
return bitSet;
public boolean readBit(int row, int column)
return code[row].get(column);
@Override
public String toString()
StringBuilder stringBuilder = new StringBuilder();
String rowSeparator = "";
for (int row = 0; row < code.length; ++row)
stringBuilder.append(rowSeparator);
rowSeparator = "n";
rowToBitString(stringBuilder, code[row]);
return stringBuilder.toString();
private void rowToBitString(StringBuilder stringBuilder, BitSet bitSet)
for (int i = 0; i != bits; ++i)
stringBuilder.append(bitSet.get(i) ? '1' : '0');
private int getDifferenceCounts(BitSet row1, BitSet row2)
int differenceCount = 0;
for (int i = 0; i < bits; ++i)
if (row1.get(i) != row2.get(i))
differenceCount++;
if (differenceCount == 2)
return differenceCount;
return differenceCount;
GrayCodeGenerator.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class provides a method for generating Gray code over particular number
* of bits.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public class GrayCodeGenerator
public static GrayCode generate(int bits)
checkBits(bits);
if (bits == 0)
return new GrayCode(new BitSet[0], 0);
BitSet bitSetArray = new BitSet[getNumberOfBitStrings(bits)];
for (int i = 0; i != bitSetArray.length; ++i)
bitSetArray[i] = new BitSet(bits);
bitSetArray[1].set(bits - 1);
for (int bitIndex = bits - 1, columnHeight = 2, width = 1;
bitIndex > 0;
bitIndex--, columnHeight <<= 1, ++width)
// Mirror down:
for (int row1 = columnHeight,
row2 = columnHeight - 1;
row1 < (columnHeight << 1);
row1++,
row2--)
for (int w = bits - 1; w > bitIndex - 1; w--)
bitSetArray[row1].set(w, bitSetArray[row2].get(w));
// Fill the prefix bits:
for (int row = columnHeight; row < (columnHeight << 1); ++row)
bitSetArray[row].set(bitIndex - 1);
return new GrayCode(bitSetArray, bits);
/**
* Returns the number of rows in the Gray code over @code bitsÃÂ bits.
*
* @param bits the number of bits.
* @return the number of rows in the resulting Gray code.
*/
private static int getNumberOfBitStrings(int bits)
return 1 << bits;
/**
* Checks that the number of bits is not negative.
*
* @param bits the number of bits to check.
*/
private static void checkBits(int bits)
if (bits < 0)
throw new IllegalArgumentException(
"Negative number of bits requested: " + bits);
GrayCodeDemo.java
package net.coderodde.graycode;
/**
* This class implements a sample Gray code demonstration.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCodeDemo
public static void main(String args)
GrayCode grayCode = GrayCodeGenerator.generate(4);
System.out.println(grayCode);
System.out.println("Valid Gray code: " + grayCode.isValid());
GrayCodeTest.java
package net.coderodde.graycode;
import java.util.BitSet;
import org.junit.Test;
import static org.junit.Assert.*;
public class GrayCodeTest
@Test
public void test()
GrayCode grayCode = GrayCodeGenerator.generate(2);
assertEquals(4, grayCode.getNumberOfRows());
assertEquals(2, grayCode.getNumberOfBits());
System.out.println(grayCode);
assertTrue(grayCode.isValid());
// Check first column:
assertFalse(grayCode.readBit(0, 0));
assertFalse(grayCode.readBit(1, 0));
assertTrue(grayCode.readBit(2, 0));
assertTrue(grayCode.readBit(3, 0));
// Check second column:
assertFalse(grayCode.readBit(0, 1));
assertTrue(grayCode.readBit(1, 1));
assertTrue(grayCode.readBit(2, 1));
assertFalse(grayCode.readBit(3, 1));
BitSet row1 = grayCode.getRow(1);
assertFalse(row1.get(0));
assertTrue(row1.get(1));
@Test
public void bruteForceTest()
for (int bits = 0; bits < 12; bits++)
assertTrue(GrayCodeGenerator.generate(bits).isValid());
Critique request
Please tell me anything that comes to mind. I am most interested in comments regarding the API design.
java algorithm unit-testing library
This library is for generating Gray codes. A Gray code over $n$ bits is a list of $2^n$ different $n$-bit strings subject to the following constraint: two adjacent bit string differ in only one position. For example, the Gray code over four bits is
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000
Without further ado, let's proceed to code.
GrayCode.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class holds the Gray code.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCode
private final BitSet code;
private final int bits;
GrayCode(BitSet code, int bits)
this.code = code;
this.bits = bits;
public boolean isValid()
if (getNumberOfBits() == 0)
return code.length == 0;
int rowLength = getNumberOfBits();
BitSet previousRow = getRow(0);
for (int row = 1; row < getNumberOfRows(); row++)
BitSet currentRow = getRow(row);
if (getDifferenceCounts(previousRow, currentRow) != 1)
return false;
previousRow = currentRow;
return true;
public int getNumberOfBits()
return bits;
public int getNumberOfRows()
return this.code.length;
public BitSet getRow(int index)
BitSet bitSet = new BitSet(getNumberOfBits());
for (int i = 0; i < bits; ++i)
bitSet.set(i, code[index].get(i));
return bitSet;
public boolean readBit(int row, int column)
return code[row].get(column);
@Override
public String toString()
StringBuilder stringBuilder = new StringBuilder();
String rowSeparator = "";
for (int row = 0; row < code.length; ++row)
stringBuilder.append(rowSeparator);
rowSeparator = "n";
rowToBitString(stringBuilder, code[row]);
return stringBuilder.toString();
private void rowToBitString(StringBuilder stringBuilder, BitSet bitSet)
for (int i = 0; i != bits; ++i)
stringBuilder.append(bitSet.get(i) ? '1' : '0');
private int getDifferenceCounts(BitSet row1, BitSet row2)
int differenceCount = 0;
for (int i = 0; i < bits; ++i)
if (row1.get(i) != row2.get(i))
differenceCount++;
if (differenceCount == 2)
return differenceCount;
return differenceCount;
GrayCodeGenerator.java
package net.coderodde.graycode;
import java.util.BitSet;
/**
* This class provides a method for generating Gray code over particular number
* of bits.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public class GrayCodeGenerator
public static GrayCode generate(int bits)
checkBits(bits);
if (bits == 0)
return new GrayCode(new BitSet[0], 0);
BitSet bitSetArray = new BitSet[getNumberOfBitStrings(bits)];
for (int i = 0; i != bitSetArray.length; ++i)
bitSetArray[i] = new BitSet(bits);
bitSetArray[1].set(bits - 1);
for (int bitIndex = bits - 1, columnHeight = 2, width = 1;
bitIndex > 0;
bitIndex--, columnHeight <<= 1, ++width)
// Mirror down:
for (int row1 = columnHeight,
row2 = columnHeight - 1;
row1 < (columnHeight << 1);
row1++,
row2--)
for (int w = bits - 1; w > bitIndex - 1; w--)
bitSetArray[row1].set(w, bitSetArray[row2].get(w));
// Fill the prefix bits:
for (int row = columnHeight; row < (columnHeight << 1); ++row)
bitSetArray[row].set(bitIndex - 1);
return new GrayCode(bitSetArray, bits);
/**
* Returns the number of rows in the Gray code over @code bitsÃÂ bits.
*
* @param bits the number of bits.
* @return the number of rows in the resulting Gray code.
*/
private static int getNumberOfBitStrings(int bits)
return 1 << bits;
/**
* Checks that the number of bits is not negative.
*
* @param bits the number of bits to check.
*/
private static void checkBits(int bits)
if (bits < 0)
throw new IllegalArgumentException(
"Negative number of bits requested: " + bits);
GrayCodeDemo.java
package net.coderodde.graycode;
/**
* This class implements a sample Gray code demonstration.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Jan 4, 2018)
*/
public final class GrayCodeDemo
public static void main(String args)
GrayCode grayCode = GrayCodeGenerator.generate(4);
System.out.println(grayCode);
System.out.println("Valid Gray code: " + grayCode.isValid());
GrayCodeTest.java
package net.coderodde.graycode;
import java.util.BitSet;
import org.junit.Test;
import static org.junit.Assert.*;
public class GrayCodeTest
@Test
public void test()
GrayCode grayCode = GrayCodeGenerator.generate(2);
assertEquals(4, grayCode.getNumberOfRows());
assertEquals(2, grayCode.getNumberOfBits());
System.out.println(grayCode);
assertTrue(grayCode.isValid());
// Check first column:
assertFalse(grayCode.readBit(0, 0));
assertFalse(grayCode.readBit(1, 0));
assertTrue(grayCode.readBit(2, 0));
assertTrue(grayCode.readBit(3, 0));
// Check second column:
assertFalse(grayCode.readBit(0, 1));
assertTrue(grayCode.readBit(1, 1));
assertTrue(grayCode.readBit(2, 1));
assertFalse(grayCode.readBit(3, 1));
BitSet row1 = grayCode.getRow(1);
assertFalse(row1.get(0));
assertTrue(row1.get(1));
@Test
public void bruteForceTest()
for (int bits = 0; bits < 12; bits++)
assertTrue(GrayCodeGenerator.generate(bits).isValid());
Critique request
Please tell me anything that comes to mind. I am most interested in comments regarding the API design.
java algorithm unit-testing library
edited Jan 4 at 19:25
asked Jan 4 at 18:12
coderodde
15.5k533114
15.5k533114
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26
add a comment |Â
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
2
down vote
accepted
As interface design is pivotal in type design, I'm happy to start there -
let me refer to java.util.BitSet
. In no uncertain terms, the documentation summarises in just two sentences what BitSet
is about: element access and
bulk boolean operations (see java.math.BigInteger
for something irritatingly similar)
(leaving out summaries (cardinality()
and intersectsâÂÂ(BitSet other)
) and paraphernalia).
I like that it is possible to have non-reflected binary codes - assuming aGrayCode(int nBits, long ... codes)
: new GrayCode(3, 0, 1, 3, 7, 6, 4)
.
I second AJD in preferring a constructor with a single int
parameter as an alternative to a separate generator class for reflected binary Gray codes.
With that change, the whole API collapses to public boolean GrayCode.isValid()
- which in itself is weird:
Objects should be constructed in a valid state and never get invalid if that can be helped.
(Another hint about the API is the lack of documentation - compare to BitSet
.)
Then, there is implementation:
getRow()
could justreturn (BitSet) code[index].clone();
int getDifferenceCount(BitSet row1, BitSet row2)
BitSet bits = (BitSet) row1.clone();
bits.xor(row2);
return bits.cardinality();
isValid()
needs to initialise BitSet previousRow = getRow(getNumberOfRows()-1);
and start from 0 to check every transition - but even that is just one necessary condition where a second comes to mind: no code may repeat. (I don't know better that to sort with a "throwing comparator".)
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
add a comment |Â
up vote
3
down vote
Personally, I would have put the generator code (and helper functions) within the GrayCode
class, not within its own class. A key point here is that there is not initialiser for the GrayCodeGenerator
class.
You can then use this to see if the gray code has been set - useful for avoiding programming errors where the future code declares a GrayCode
but does not generate with it.
You could also use this for a new constructor where only a number of bits is passed, and the GrayCode
class then automatically generates the BitSet
. Yes, you could also do this with the current code, but having the generator inside the GrayCode
class will make it neater.
add a comment |Â
up vote
1
down vote
What is a bit missing, is the logic / proof / explanation. And it is generative, creating a sequence.
Hence one could look at an immediate mapping function:
static int grayCode(int n) grayCode(high - 1 - lows); // Reverse order backwards
- Proof can be done by induction because of the recursion.
- The recursion can be resolved a bit. (Also generative with a non-tail recursion.)
- An explanation is simple too:
Having a valid sequence of 0 .. 2k - 1, the following 2k numbers can be retrieved by reversing the list and adding a bit 1 in front: every step also flips one single bit.
I did not want to spoil this nice usage of BitSet, but Gray Codes seem useful, like de-Bruijn sequences.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
As interface design is pivotal in type design, I'm happy to start there -
let me refer to java.util.BitSet
. In no uncertain terms, the documentation summarises in just two sentences what BitSet
is about: element access and
bulk boolean operations (see java.math.BigInteger
for something irritatingly similar)
(leaving out summaries (cardinality()
and intersectsâÂÂ(BitSet other)
) and paraphernalia).
I like that it is possible to have non-reflected binary codes - assuming aGrayCode(int nBits, long ... codes)
: new GrayCode(3, 0, 1, 3, 7, 6, 4)
.
I second AJD in preferring a constructor with a single int
parameter as an alternative to a separate generator class for reflected binary Gray codes.
With that change, the whole API collapses to public boolean GrayCode.isValid()
- which in itself is weird:
Objects should be constructed in a valid state and never get invalid if that can be helped.
(Another hint about the API is the lack of documentation - compare to BitSet
.)
Then, there is implementation:
getRow()
could justreturn (BitSet) code[index].clone();
int getDifferenceCount(BitSet row1, BitSet row2)
BitSet bits = (BitSet) row1.clone();
bits.xor(row2);
return bits.cardinality();
isValid()
needs to initialise BitSet previousRow = getRow(getNumberOfRows()-1);
and start from 0 to check every transition - but even that is just one necessary condition where a second comes to mind: no code may repeat. (I don't know better that to sort with a "throwing comparator".)
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
add a comment |Â
up vote
2
down vote
accepted
As interface design is pivotal in type design, I'm happy to start there -
let me refer to java.util.BitSet
. In no uncertain terms, the documentation summarises in just two sentences what BitSet
is about: element access and
bulk boolean operations (see java.math.BigInteger
for something irritatingly similar)
(leaving out summaries (cardinality()
and intersectsâÂÂ(BitSet other)
) and paraphernalia).
I like that it is possible to have non-reflected binary codes - assuming aGrayCode(int nBits, long ... codes)
: new GrayCode(3, 0, 1, 3, 7, 6, 4)
.
I second AJD in preferring a constructor with a single int
parameter as an alternative to a separate generator class for reflected binary Gray codes.
With that change, the whole API collapses to public boolean GrayCode.isValid()
- which in itself is weird:
Objects should be constructed in a valid state and never get invalid if that can be helped.
(Another hint about the API is the lack of documentation - compare to BitSet
.)
Then, there is implementation:
getRow()
could justreturn (BitSet) code[index].clone();
int getDifferenceCount(BitSet row1, BitSet row2)
BitSet bits = (BitSet) row1.clone();
bits.xor(row2);
return bits.cardinality();
isValid()
needs to initialise BitSet previousRow = getRow(getNumberOfRows()-1);
and start from 0 to check every transition - but even that is just one necessary condition where a second comes to mind: no code may repeat. (I don't know better that to sort with a "throwing comparator".)
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
As interface design is pivotal in type design, I'm happy to start there -
let me refer to java.util.BitSet
. In no uncertain terms, the documentation summarises in just two sentences what BitSet
is about: element access and
bulk boolean operations (see java.math.BigInteger
for something irritatingly similar)
(leaving out summaries (cardinality()
and intersectsâÂÂ(BitSet other)
) and paraphernalia).
I like that it is possible to have non-reflected binary codes - assuming aGrayCode(int nBits, long ... codes)
: new GrayCode(3, 0, 1, 3, 7, 6, 4)
.
I second AJD in preferring a constructor with a single int
parameter as an alternative to a separate generator class for reflected binary Gray codes.
With that change, the whole API collapses to public boolean GrayCode.isValid()
- which in itself is weird:
Objects should be constructed in a valid state and never get invalid if that can be helped.
(Another hint about the API is the lack of documentation - compare to BitSet
.)
Then, there is implementation:
getRow()
could justreturn (BitSet) code[index].clone();
int getDifferenceCount(BitSet row1, BitSet row2)
BitSet bits = (BitSet) row1.clone();
bits.xor(row2);
return bits.cardinality();
isValid()
needs to initialise BitSet previousRow = getRow(getNumberOfRows()-1);
and start from 0 to check every transition - but even that is just one necessary condition where a second comes to mind: no code may repeat. (I don't know better that to sort with a "throwing comparator".)
As interface design is pivotal in type design, I'm happy to start there -
let me refer to java.util.BitSet
. In no uncertain terms, the documentation summarises in just two sentences what BitSet
is about: element access and
bulk boolean operations (see java.math.BigInteger
for something irritatingly similar)
(leaving out summaries (cardinality()
and intersectsâÂÂ(BitSet other)
) and paraphernalia).
I like that it is possible to have non-reflected binary codes - assuming aGrayCode(int nBits, long ... codes)
: new GrayCode(3, 0, 1, 3, 7, 6, 4)
.
I second AJD in preferring a constructor with a single int
parameter as an alternative to a separate generator class for reflected binary Gray codes.
With that change, the whole API collapses to public boolean GrayCode.isValid()
- which in itself is weird:
Objects should be constructed in a valid state and never get invalid if that can be helped.
(Another hint about the API is the lack of documentation - compare to BitSet
.)
Then, there is implementation:
getRow()
could justreturn (BitSet) code[index].clone();
int getDifferenceCount(BitSet row1, BitSet row2)
BitSet bits = (BitSet) row1.clone();
bits.xor(row2);
return bits.cardinality();
isValid()
needs to initialise BitSet previousRow = getRow(getNumberOfRows()-1);
and start from 0 to check every transition - but even that is just one necessary condition where a second comes to mind: no code may repeat. (I don't know better that to sort with a "throwing comparator".)
answered Jan 4 at 23:35
greybeard
1,3231521
1,3231521
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
add a comment |Â
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
Your beard keeps growing, thanks! ;-)
â coderodde
Jan 5 at 14:54
add a comment |Â
up vote
3
down vote
Personally, I would have put the generator code (and helper functions) within the GrayCode
class, not within its own class. A key point here is that there is not initialiser for the GrayCodeGenerator
class.
You can then use this to see if the gray code has been set - useful for avoiding programming errors where the future code declares a GrayCode
but does not generate with it.
You could also use this for a new constructor where only a number of bits is passed, and the GrayCode
class then automatically generates the BitSet
. Yes, you could also do this with the current code, but having the generator inside the GrayCode
class will make it neater.
add a comment |Â
up vote
3
down vote
Personally, I would have put the generator code (and helper functions) within the GrayCode
class, not within its own class. A key point here is that there is not initialiser for the GrayCodeGenerator
class.
You can then use this to see if the gray code has been set - useful for avoiding programming errors where the future code declares a GrayCode
but does not generate with it.
You could also use this for a new constructor where only a number of bits is passed, and the GrayCode
class then automatically generates the BitSet
. Yes, you could also do this with the current code, but having the generator inside the GrayCode
class will make it neater.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Personally, I would have put the generator code (and helper functions) within the GrayCode
class, not within its own class. A key point here is that there is not initialiser for the GrayCodeGenerator
class.
You can then use this to see if the gray code has been set - useful for avoiding programming errors where the future code declares a GrayCode
but does not generate with it.
You could also use this for a new constructor where only a number of bits is passed, and the GrayCode
class then automatically generates the BitSet
. Yes, you could also do this with the current code, but having the generator inside the GrayCode
class will make it neater.
Personally, I would have put the generator code (and helper functions) within the GrayCode
class, not within its own class. A key point here is that there is not initialiser for the GrayCodeGenerator
class.
You can then use this to see if the gray code has been set - useful for avoiding programming errors where the future code declares a GrayCode
but does not generate with it.
You could also use this for a new constructor where only a number of bits is passed, and the GrayCode
class then automatically generates the BitSet
. Yes, you could also do this with the current code, but having the generator inside the GrayCode
class will make it neater.
answered Jan 4 at 20:33
AJD
1,0351213
1,0351213
add a comment |Â
add a comment |Â
up vote
1
down vote
What is a bit missing, is the logic / proof / explanation. And it is generative, creating a sequence.
Hence one could look at an immediate mapping function:
static int grayCode(int n) grayCode(high - 1 - lows); // Reverse order backwards
- Proof can be done by induction because of the recursion.
- The recursion can be resolved a bit. (Also generative with a non-tail recursion.)
- An explanation is simple too:
Having a valid sequence of 0 .. 2k - 1, the following 2k numbers can be retrieved by reversing the list and adding a bit 1 in front: every step also flips one single bit.
I did not want to spoil this nice usage of BitSet, but Gray Codes seem useful, like de-Bruijn sequences.
add a comment |Â
up vote
1
down vote
What is a bit missing, is the logic / proof / explanation. And it is generative, creating a sequence.
Hence one could look at an immediate mapping function:
static int grayCode(int n) grayCode(high - 1 - lows); // Reverse order backwards
- Proof can be done by induction because of the recursion.
- The recursion can be resolved a bit. (Also generative with a non-tail recursion.)
- An explanation is simple too:
Having a valid sequence of 0 .. 2k - 1, the following 2k numbers can be retrieved by reversing the list and adding a bit 1 in front: every step also flips one single bit.
I did not want to spoil this nice usage of BitSet, but Gray Codes seem useful, like de-Bruijn sequences.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
What is a bit missing, is the logic / proof / explanation. And it is generative, creating a sequence.
Hence one could look at an immediate mapping function:
static int grayCode(int n) grayCode(high - 1 - lows); // Reverse order backwards
- Proof can be done by induction because of the recursion.
- The recursion can be resolved a bit. (Also generative with a non-tail recursion.)
- An explanation is simple too:
Having a valid sequence of 0 .. 2k - 1, the following 2k numbers can be retrieved by reversing the list and adding a bit 1 in front: every step also flips one single bit.
I did not want to spoil this nice usage of BitSet, but Gray Codes seem useful, like de-Bruijn sequences.
What is a bit missing, is the logic / proof / explanation. And it is generative, creating a sequence.
Hence one could look at an immediate mapping function:
static int grayCode(int n) grayCode(high - 1 - lows); // Reverse order backwards
- Proof can be done by induction because of the recursion.
- The recursion can be resolved a bit. (Also generative with a non-tail recursion.)
- An explanation is simple too:
Having a valid sequence of 0 .. 2k - 1, the following 2k numbers can be retrieved by reversing the list and adding a bit 1 in front: every step also flips one single bit.
I did not want to spoil this nice usage of BitSet, but Gray Codes seem useful, like de-Bruijn sequences.
answered Jan 5 at 16:22
Joop Eggen
987612
987612
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184299%2fa-tiny-java-library-for-generating-gray-codes%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
(Was about to dismiss this (because no purpose stated or leaping at me), but, wait: this isn't reflected binary, only?)
â greybeard
Jan 4 at 19:10
@greybeard Added some more content to the critique request.
â coderodde
Jan 4 at 19:26