按位操作逻辑

时间:2016-11-19 18:11:04

标签: python arrays list

我有两个大小相等的数组(array1和array2),分别为0和1。如何将所有与array1结合的数组生成到array2?例如,如果array1 = [1,1,1]并且array2 = [1,1,1]。输出应该是所有八个数组:[0,0,0],[1,0,0],....,[1,1,1]。有没有有效的解决方案,或者只有蛮力是这样的?

我的尝试:
我首先尝试计算比特差异,如果任何比特为负则返回false(不可能将第一个数组与任何类型的数组组合以获得array2)。如果所有位都是非负的那么....如果差异中的位为0则它也可以被0或1替换(这是错误的假设,但如果array1 = [0,0]则失败,array2 = [0 ,0],如果差异中的任何位为0,则所需的数组必须在该位置具有1以使其为1

3 个答案:

答案 0 :(得分:1)

以下是我将如何解决这个问题:

  1. 首先,让我们考虑一下。您需要找到所有二进制值数组,当它们(通过某些运算符)与已知二进制值组合时,=一个新的二进制值。不要试图解决问题。假设你需要从00到11。有多少可能的答案?假设您需要从11到11。有多少可能的答案?你能做得比(在最坏的情况下)做得更好吗?这将给你一个复杂的约束。
  2. 考虑到这个粗略的约束,解决有点好奇的问题。深入研究这个问题。什么是'按位联合运算符'?是'和'?是'还是'?它更复杂吗? “Bitwise Union”听起来像B[i] = A[i] OR X[i],但是任何提出问题的人都意味着别的......
  3. 根据问题1和2的答案,您可以在这里使用很多东西。我可以想到几个不同的选项,但我想从这里你可以想出一个算法。
  4. 一旦你有了一个解决方案,你需要考虑“我能在这里做得更好吗?”很多可以追溯到关于问题的最初印象以及它们是如何构建的,以及你有多少/多少认为你可以优化。

答案 1 :(得分:1)

注意:我将通过示例输入解释以下内容: A = [0 0 1 0 1 1], B = [1 1 1 0 1 1]

假设您要为等式X计算A OR X = B,让我们看看A和B中每个位选择的选项是什么:

A    OR    X   =   B
--------------------
0          0       0
0          1       1
1          N.A.    0
1         (0,1)    1
  1. 如果A中的任何位为1,且其对应的B位为0,则无法使用解决方案。返回一个空集。
  2. 如果AB中的相应位为1,则X中的相应位无关紧要。
  3. 现在,请看X的一个解决方案是B本身,(如果条件#1,如上所述,则满足)。因此,让我们构造一个数字start_num = B。这将是一个解决方案,其他解决方案将由此构建。

    start_num = B = [1 1 1 0 1 1]

    “选择”位是X可以取任何值的位,即A=1B=1的位置。让我们创建另一个数字choice = A AND B,以便choice = 1表示这些位置。另请注意,如果k位置choice = 1,则解决方案的总数为2^k

    choice = A AND B = [0 0 1 0 1 1] ,因此, k = 3

    将这些“选择”位置存储在一个数组(长度为k)中,从右边开始(LSB = 0)。我们称这个数组为pos_array

    pos_array = [0 1 3]

    请注意start_num中的所有'choice'位都设置为1.因此,所有其他解决方案都会将这些位中的一些(1 <= p <= k)设置为0.现在我们知道哪个要改变比特,我们需要以有效的方式制定这些解决方案。

    这可以通过使所有解决方案按照先前解决方案与当前解决方案之间的差异仅在一个位置的顺序来完成,从而使得计算解决方案变得有效。例如,如果我们有两个“选择”位,下面解释了在算术级数中简单地运行所有组合并以1位变化顺序执行它们之间的区别:

    1-bit-toggle-order                decreasing order
    ----------------------            ----------------------
    1 1   // start                    1 1   // start                       
    1 0   // toggle bit 0             1 0   // subtract 1
    0 0   // toggle bit 1             0 1   // subtract 1
    0 1   // toggle bit 0             0 0   // subtract 1 
    

    (我们希望利用按位运算的速度,因此我们将使用1位切换顺序。)

    现在,我们将构建每个解决方案:(这不是实际的C代码,只是一个解释)

    addToSet(start_num);    // add the initial solution to the set
    
    for(i=1; i<2^k; i++)
    {
        pos = 0;
        count = i;
        while( ( count & 1) != 0)
        {
            count = count>>1;
            pos++;
        }
    
        toggle(start_num[pos_array[pos]]);    // update start_num by toggling the desired bit
        addToSet(start_num);    // Add the updated vector to the set
    }
    

    如果在上面的示例中运行此代码,则将执行以下切换语句:

    toggle(start_num[0])
    toggle(start_num[1])
    toggle(start_num[0])
    toggle(start_num[3])
    toggle(start_num[0])
    toggle(start_num[1])
    toggle(start_num[0])
    

    ,这将导致以下添加:

    addToSet([1 1 1 0 1 0])
    addToSet([1 1 1 0 0 0])
    addToSet([1 1 1 0 0 1])
    addToSet([1 1 0 0 0 1])
    addToSet([1 1 0 0 0 0])
    addToSet([1 1 0 0 1 0])
    addToSet([1 1 0 0 1 1])
    

    ,除了已经存在的初始解[1 1 1 0 1 1]之外,还完成了集合。

    注意:除了其他方面,我不是按位操作的专家。我认为有更好的方法来编写算法,更好地利用位访问指针和按位二进制操作(如果有人可以建议改进,将会很高兴)。我提出的解决方案是解决这个问题的一般方法。

答案 2 :(得分:0)

您可以通过评估:

为每个广告位i构建数字选项
for d in (0, 1):
    if (array1[i] or d) == array2[i]):
        digits[i].append(d)

然后你只需要迭代i 目标是构建一个列表列表:[[0,1],[1],[0,1]]显示每个槽中的有效数字。然后,您可以使用itertools.product()构造所有有效数组:

arrays = list(itertools.product(*digits))

您可以使用列表推导将所有这些组合在一起,这将导致:

list(it.product(*[[d for d in (0, 1) if (x or d) == y] for x, y in zip(array1, array2)]))

行动中:

>>> import itertools as it
>>> a1, a2 = [1,1,1], [1,1,1]
>>> list(it.product(*[[d for d in (0, 1) if (x or d) == y] for x, y in zip(a1, a2)]))
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]

>>> a1, a2 = [1,0,0], [1,1,1]
>>> list(it.product(*[[d for d in (0, 1) if (x or d) == y] for x, y in zip(a1, a2)]))
[(0, 1, 1), (1, 1, 1)]

>>> a1, a2 = [1,0,0], [0,1,1]
>>> list(it.product(*[[d for d in (0, 1) if (x or d) == y] for x, y in zip(a1, a2)]))
[]