大多数二进制组合来自4位,每位单次更改

时间:2009-01-16 14:53:29

标签: algorithm design-patterns binary combinations

我有4个二进制位

Bit 3  Bit 2  Bit 1  Bit 0

通常答案很简单:2 ^ 4,或16种不同的组合;它看起来像下面这样:

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

但是,LSB(位0)每次迭代都会改变状态。

我需要一种算法,其中一个位的状态仅在所有迭代中改变一次;即,我需要所有的位都像MSB(位3)。

我该怎么做?

修改

似乎大多数人正在融合只有5种可能的解决方案。然而,这假设有一个起点和一个终点。这无所谓,所以我将给出一个真实世界的场景来更好地解释。

假设我有一个数字闹钟,可以提供4个输出。每个输出可以被编程为在特定时间继续并且在特定时间关闭并且彼此独立地编程,例如。我可以将输出1编程为上午1点和凌晨3点关闭,而我可以将输出2编程为下午7点和下午2点关闭。每个输出可以保持多长时间没有限制。

现在我想将这个闹钟挂在电脑上并尽可能接近当前的正确时间。即如果时钟表示时间是下午2:15,我的计算机就知道警报在下午12点到下午6点的范围内。我希望能够获得尽可能小的范围。什么是我能得到的最小范围?

9 个答案:

答案 0 :(得分:12)

  1. 有4位。
  2. 每个位只能更改一次状态。
  3. 对于每个新值,至少有一个位必须从先前的值更改状态。
  4. 因此,您最多可以有4个状态更改,最多可以有5个不同的值。

    示例:

    0000 -> 0001 -> 0011 -> 0111 -> 1111
    

    修改

    很好,让我们重温你的意思,而不是你所说的。

    1. 有4位。
    2. 每个位只能改变状态两次。 (一次从0到1,一次从1到0)
    3. 对于每个新值,至少有一个位必须从先前的值更改状态。
    4. 因此,您最多可以有8个状态更改,最多可以有8个不同的值(因为最后一次状态更改必然会将所有位恢复到初始状态)

      示例:

      0000 -> 0001 -> 0011 -> 0111 -> 1111 -> 1110 -> 1100 -> 1000 -> 0000
      

      因此,通过将输出设置为:3 AM - 3 PM,6 AM - 6 PM,9 AM - 9 PM和中午 - 午夜,您可以确定输出的3小时周期。我建议将电线插入视觉输出中。

答案 1 :(得分:7)

你想要一个Gray Code。看看“构造一个n位格雷码”的一半。

答案 2 :(得分:3)

我认为通过这种限制循环所有可能的位模式是不可能的。

如果你有一个n位的想法,你可以循环通过总共(n + 1)个状态,然后再翻转你已经翻过的一个。

例如,在一个3位示例中,如果从111开始,则得到

111
110
100
000

然后你被迫翻转一个你已经翻过来获得新状态的人。

答案 3 :(得分:1)

根据您的闹钟示例,我假设您需要完成您开始的组合,并且每个位都可以循环然后关闭一次,例如

  <00> 0000 - &gt; 0001 - &gt; 0011 - &gt; 0111 - &gt; 1111    - &GT; 1110 - &gt; 1100 - &gt; 1000 - &gt; 0000

步数是位数的两倍,因此使用4位可以使当前时间在3小时范围内。

答案 4 :(得分:0)

您希望每个位只更改一次吗?

像:

0000 -> 0001 -> 0011 -> 0111 -> 1111 

在这种情况下,你可以使用一个简单的计数器,其中delta每次迭代乘以2(或向左移动)。

答案 5 :(得分:0)

如果Gamecat让你正确, 您的位掩码值将是:

 1 - 1 
 2 - 1 
 4 - 1
 8 - 1
 16 - 1
 etc.
 2^i - 1

或使用班次:  (1&lt;&lt; i) - 1 for 0 in 0 ..

答案 6 :(得分:0)

“我需要一种算法,其中一个位的状态仅在所有迭代中改变一次”

如果按字面意思采用上述陈述,则每次迭代只有五种状态,如其他帖子所述。

如果问题是“可以生成多少个可能的序列?”,那么:

第一个州是否总是0000?

如果没有,那么您有16种可能的初始状态。

订单有关系吗?

如果是,那么你有4个! = 24种可能的方法来选择首先翻转的位。

因此,这总共可以生成16 * 24 = 384个可能的序列。

答案 7 :(得分:0)

以下是一个示例,说明如何只保留一次翻转。不知道你系统的所有参数是不容易给出一个准确的例子,但无论如何这里都是一个。

char bits = 0x05;
flipp_bit(char bit_flip)
{
    static char bits_flipped=0;
    if( (bits_flipped & bit_flip) == 0)
    {
        bits_flipped |= bit_flip;
        bits ^= bit_flip;
    }
}

翻转此功能只允许每个位翻转一次。

答案 8 :(得分:0)

回顾原始问题,我想我明白你的意思

根据可能的位组合数量,简单地描述可用于编程时钟的最小位数

第一个问题是需要多少序列。

60秒x 60分钟x 24小时= 86400(需要组合) 下一步是计算生成至少86400种组合所需的位数

如果有人知道计算

多少位可以产生86400种组合,那就是你的答案。 希望在某个地方有一个在线计算公式