4

I am looking for a clean way to list the (8 bit) integers whose binary representation is not the same as another integer up to rotation and reflection.

For example the list will probably start as
0
1
(2=10b is skipped because you can rotate the bits in 1, therefore all powers of 2 are skipped. Also every number except 0 will be odd)
3=11b
5=101b 7=111b
9=1001b 11=1011b (so 13=1101b will be skipped because 11010000b is a reflection of 1101b which can then be rotated to the right 4 times ) .
.
.

Also ideally how could this be generalized to numbers with different numbers of bits, (16, 32, or just n) and other bases beside 2.

John Smith
  • 12,491
  • 18
  • 65
  • 111
  • I am supposing that 0000 0011 is considered a rotation of 1000 0001 – P i Nov 07 '10 at 09:37
  • 1
    the answers here: http://stackoverflow.com/questions/262826/good-simple-algorithm-for-generating-necklaces-in-scheme may be illuminating. – High Performance Mark Nov 07 '10 at 11:33
  • @High Performance Mark. Yours has been the best answer so far. – John Smith Nov 07 '10 at 14:19
  • What I have is the necklace problem. I just didn't know the name. What I am asking for (and some people have missed) is a **clean, elegant** way to enumerate all the necklaces. It's not difficult to do it ad-hoc, but then it's harder to analyze or generalize. – John Smith Nov 07 '10 at 19:29

4 Answers4

1

Since @John Smith thought my comment was a good answer, here it is an answer.

The answers here may be illuminating.

Community
  • 1
  • 1
High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
0

Thanks to Jeffromi for explaining the problem better -- I've deleted my previous answer.

Here's another solution in Perl. Perl is a good language for this sort of problem because it makes it easy to treat numbers as text and text as numbers.

i: for $i (0..255) {
  $n1 = sprintf "%08b", $i;    # binary representation of $i

  $n2 = $n1;                   # "unreflected" copy of $n1
  $n3 = reverse $n1;           # "reflection" of $n1 

  for $j (1..8) {
    $n2 = chop($n2) . $n2;     # "rotate" $n2
    $n3 = chop($n3) . $n3;     # "rotate" $n3
    next i if $found{$n2} or $found{$n3};
  }

  # if we get here, we rotated $n2 and $n3 8 times
  # and didn't get a nonsymmetric byte that we've
  # seen before -- this is a nonsymmetric byte
  $found{$n1}++;
  print "$i   $n1\n";
}

This isn't as simple as the previous solution, but the jist is to try out all 16 combinations (2 reflections x 8 rotations) and compare them with all of the nonsymmetric bytes you've seen before.

There's a operator for bit shifting with rotation in Perl, but the chop($num) . $num idiom I used generalizes better to problems with base n.

socket puppet
  • 3,191
  • 20
  • 16
0

You can use a sieve, similar to the sieve of Eratosthenes for prime numbers.

Use a bit array (BitSet in Java) with one bit for each number.

Initially mark all bits.

Go sequentially through the bit array until you find the next bit that is set at index n, this is a number in your set. Then clear the bits of all other numbers that can be reached from n via rotation and mirroring.

On today's machines this is feasible up to 32 bits, which would use 512MB of memory.

starblue
  • 55,348
  • 14
  • 97
  • 151
0

An alternative solution to Eratosthenes' Sieve would be to construct a test T(k) that returns True or False for any given k.

It would be slower, but this way no storage would be needed, so it would extend more readily to arbitrary data length.

If you simplify the problem for a moment, and say we are simply looking to discard reflections, then it would be easy:

T_ref(k) returns true iff k <= Reflection(k).

As for rotating bits, exactly the same can be done:

T_rot(k) returns true iff k == MIN{the set of all rotations of k}

You can think of dividing your integers up into a bunch of equivalence classes E(k) where E(k) is the set of all reflection&rotation permutations of k.

You might want to take a moment to satisfy yourself that the set of natural numbers N partitions itself readily into such disjoint subsets.

Then the set

{k s.t. k == MIN(E(k)) } 

will guarantee to contain exactly one element from each equivalence class.

This would make a really nice interview question.

P i
  • 29,020
  • 36
  • 159
  • 267