我有两个大小相等的数组(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
答案 0 :(得分:1)
以下是我将如何解决这个问题:
B[i] = A[i] OR X[i]
,但是任何提出问题的人都意味着别的...... 答案 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
A
中的任何位为1,且其对应的B
位为0,则无法使用解决方案。返回一个空集。A
和B
中的相应位为1,则X
中的相应位无关紧要。现在,请看X
的一个解决方案是B
本身,(如果条件#1,如上所述,则满足)。因此,让我们构造一个数字start_num = B
。这将是一个解决方案,其他解决方案将由此构建。
start_num = B = [1 1 1 0 1 1]
“选择”位是X
可以取任何值的位,即A=1
和B=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)]))
[]