计算非对称字节

时间:2010-11-07 04:36:34

标签: language-agnostic math binary bit-manipulation

我正在寻找一种简洁的方法来列出(8位)整数,其二进制表示与另一个整数相同,直到旋转和反射。

例如,列表可能以as开头 0
1
(2 =跳过10b,因为你可以将位旋转为1,因此跳过所有2的幂。除了0之外的每个数字都是奇数)
3 = 11b时
5 = 101B 7 = 111B
9 = 1001B 11 = 1011b(因此13 = 1101b将被跳过,因为11010000b是1101b的反射,然后可以向右旋转4次) 。

理想情况下,如何将其推广到具有不同位数(16,32或仅 n )的数字以及除2之外的其他基数。

4 个答案:

答案 0 :(得分:1)

由于@John Smith认为我的评论很好,所以这是一个答案。

The answers here可能很有启发性。

答案 1 :(得分:0)

感谢Jeffromi更好地解释了这个问题 - 我删除了之前的答案。

这是Perl的另一个解决方案。 Perl是解决这类问题的好语言,因为它可以很容易地将数字视为文本,将文本视为数字。

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";
}

这不像以前的解决方案那么简单,但是jist将尝试所有16种组合(2次反射x 8次旋转)并将它们与您之前看到的所有非对称字节进行比较。

在Perl中有一个用于旋转位移的运算符,但我使用的chop($num) . $num惯用语更好地概括了 n 的基本问题。

答案 2 :(得分:0)

您可以使用类似于Eratosthenes筛子的筛子作为素数。

在Java中使用位数组(BitSet),每个数字都有一位。

最初标记所有位。

顺序遍历位数组,直到找到在索引n设置的下一位,这是您集合中的数字。然后清除可以通过旋转和镜像从n到达的所有其他数字的位。

在今天的机器上,这是可行的,最多32位,这将使用512MB的内存。

答案 3 :(得分:0)

Eratosthenes'Sieve的另一种解决方案是构建一个测试T(k),对任何给定的k都返回True或False。

速度会慢一些,但这样就不需要存储空间,因此可以更容易地扩展到任意数据长度。

如果你暂时解决问题,并说我们只是想放弃反射,那么这很容易:

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

至于旋转位,可以完全相同:

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

你可以考虑将你的整数划分为一堆等价类E(k),其中E(k)是k的所有反射和旋转排列的集合。

您可能需要花一点时间来确定自然数字N的集合很容易分成这些不相交的子集。

然后设置

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

将保证每个等价类中只包含一个元素。

这会成为一个非常好的面试问题。