想知道是否有一种方法可以在两个列表上使用itertools.permutations()
(或其他类似方法),并以某种方式链接两个列表的输出,从而在它们的输出之间存在一对一的映射。 / p>
示例:我有一个字节x = 0xE3, x_bit = BitArray(x).bin = 11100011
,它是八个信号(位流)(d0-d7)
(例如[d0,d3,d4,d7,d2,d1,d6,d5]
)的特定顺序的结果。如果我想重新排列信号的顺序,例如得到0xEC = 11101100
由于二进制域的非唯一性,我有几种可能性,但是两种可能性是[d0,d3,d4,d7,d6,d6,d1,d2]
和[d3,d0,d4,d7,d6,d6,d1,d2]
0xEC
的输出链接到数据信号(d0-d7)
的顺序,该信号产生所需的比特序列,例如。以一种方式“钩住”原始信号顺序到不同的位,以便最终得到可能组合的列表,但又不丢失二进制排列提供的非唯一性?我最初想到的是将信号名称作为字符串附加到位值之后,但是当然,它将是列表中的唯一条目,并且并非所有有效的排列都将包含在结果中。
这是我最终将在5-6个字节的字节数组上使用的东西,因此最终我将必须保存所有组合,以使数组的所有字节位置上都得到所需的输出,但是由于时间,首先是事情。
import itertools
import bitstring
input_byte = 0xE3
input_bitseq = bitstring.BitArray(inpu_byte) # 1110 0011
signal_order = ['d0','d3','d4','d7','d2','d1','d6','d5'] # input signal order
perms = list(itertools.permutations(intput_bitseq))
for x in perms:
print(x)
示例输出:
('1', '1', '1', '0', '0', '0', '1', '0')
('1', '1', '0', '1', '0', '0', '1', '1')
('1', '1', '1', '0', '0', '1', '1', '0')
('1', '1', '0', '0', '1', '1', '0', '1')
('1', '1', '0', '0', '1', '1', '1', '0')
('1', '1', '0', '0', '1', '1', '0', '1')
('1', '1', '0', '0', '1', '0', '1', '1')
('1', '1', '0', '0', '1', '0', '1', '1')
('1', '1', '0', '0', '1', '1', '1', '0')
(列表将有40k条目)。现在,这些条目中只有一个子集实际上等于0xEC
,这些当然很容易找到,但是我还想知道映射到不同位序列的信号(d0-d7)的哪种组合,全部匹配0xEC
。
额外说明:
Original data:
MSB b7,b6,b5,b4,b3,b2,b1,b0 LSB
0x90 0xE3 0xF5 0xB0 0x9F 0xA2
1001 0000 1110 0011 1111 0101 1011 0000 1001 1111 1010 0010
Switch positions: b1<->b3, b0<->b2
MSB b7,b6,b5,b4,b1,b0,b3,b2 LSB
0x90 0xEC 0xF5 0xB0 0x9F 0xA8
1001 0000 1110 1100 1111 0101 1011 0000 1001 1111 1010 1000
Switch positions: b1<->b0, b3<->b2
MSB b7,b6,b5,b4,b0,b1,b2,b3 LSB
0x90 0xEC 0xFA 0xB0 0x9F 0xA4
1001 0000 1110 1100 1111 1010 1011 0000 1001 1111 1010 0100
Switch positions: b5<->b1
MSB b7,b6,b1,b4,b0,b5,b2,b3 LSB
0x90 0xEC 0xDE 0x94 0xBB 0xA4
1001 0000 1110 1100 1101 1110 1001 0100 1011 1011 1010 0100
Switch positions: b0<->b6
MSB b7,b0,b1,b4,b6,b5,b2,b3 LSB
Final/desired output
0x90 0xEC 0xDE 0x94 0xF3 0xA4
1001 0000 1110 1100 1101 1110 1001 0100 1111 0011 1010 0100
答案 0 :(得分:0)
我不确定100%是否了解您要在这里做什么。据我了解,您希望源位数组中产生目标位数组的所有位置排列。
幼稚的方法是生成所有排列,然后检查其中哪些与目标相对应,但将是8! = 40k
排列。这不是很多,但是对于较长的序列或经常这样做时可能是个问题。或者,您可以获取1和0的所有排列,并将其分配以适合您的结果;在您的示例中,这些只是5!*3! = 720
(更均衡==更少/更好)。
类似这样的事情(注意:我只是使用字符串而不是BitArray,但这在这里不重要)
>>> bits = "11100011"
>>> trgt = "11101100"
>>> ones = [i for i, e in enumerate(bits) if e == "1"]
>>> zeros = [i for i, e in enumerate(bits) if e == "0"]
>>> from itertools import permutations
>>> res = [[next(p1 if b == "1" else p2) for b in trgt] for p1, p2 in
... ((iter(p1), iter(p2)) for p1 in permutations(ones)
... for p2 in permutations(zeros))]
...
>>> res[0]
[0, 1, 2, 3, 6, 7, 4, 5]
>>> len(res)
720
>>> set(''.join(bits[i] for i in l) for l in res)
{'11101100'}
这为您提供了一个字节的解决方案。现在,如果我正确理解了多字节部分,那么您正在寻找一种可以应用于 all 个字节的位转换。在这种情况下,解决方案的数量确实会迅速减少。您可以使用上述算法获取单个字节的所有解决方案,然后获取其中的set.intersection
(首先将列表转换为元组以使其可哈希化),或者获取第一个字节的解决方案(或更优) :最“平衡”的解决方案,以最少的解决方案开始),然后检查其中哪些解决方案也可以解决其他问题。