【问题标题】:Permutation of two "linked" lists in pythonpython中两个“链接”列表的排列
【发布时间】:2019-01-21 19:34:06
【问题描述】:

想知道是否有办法在两个列表上使用itertools.permutations()(或其他或类似的东西)并以某种方式链接两者的输出,因此它们的输出之间存在一对一的映射。

示例:我有一个字节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

【问题讨论】:

  • 你能给我们看一些示例代码吗?我很难理解你正在尝试做的事情。我也看不出这与链表有什么关系。
  • 不完全清楚你想要什么:导致目标列表的原始列表的所有排列?
  • 现在尝试编写一些示例代码,希望它变得更清晰。给我几分钟。
  • 一种天真的方法是生成所有排列,然后检查其中哪些对应于目标,但这些排列将是 8!=40k 排列。或者,您可以获取 1 和 0 的所有排列并分配它们以适合您的结果;在您的示例中,这些只是 5!*3!=720。
  • 现在@tobias_k 为原始问题添加了一些信息。我还没有尝试过,但我只是想,也许可以制作一个字典并对值进行排列,但输出中的键和值之间仍然存在联系?

标签: python permutation itertools


【解决方案1】:

我不能 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(首先将列表转换为元组以使其可散列),或者获取第一个字节的解决方案(或更好:最“平衡”的一个,开始时解决方案的数量最少),然后检查其中哪些也解决了其他问题。

【讨论】:

    猜你喜欢
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-05
    相关资源
    最近更新 更多