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 re开发者_如何转开发flection 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.
Since @John Smith thought my comment was a good answer, here it is an answer.
The answers here may be illuminating.
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.
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.
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.
精彩评论