繁体   English   中英

如何有效地创建对特定字符有限制的排列?

[英]How can i create a permutation with a limit on specific characters efficently?

让您了解我在说什么。 这是我现在拥有的代码:

chrs = 'ABCDEF1234567890'
with open('two.txt', 'w') as two:
    for xs in itertools.product(chrs, repeat=10):
        h = sum(x.isalpha() for x in xs)
        if h == 2: two.write(''.join(xs) + '\n')

不幸的是,这实际上需要几天的时间,因为它会创建所有可能的组合,但大多数组合都不匹配。

编辑:为了澄清,我需要一种方法来找到只有两个字母('ABCDEF')的变量chrs的所有可能组合。 无需创建所有组合的完整列表并检查每个组合。 我只需要创建其中有两个字母的字母即可。

更进一步:

'AA12345678' = Good
'1234A123A4' = Good
'AAA1234567' = Bad
'A123456789' = Bad

我真的不知道我还能解释五行Python代码。

这基于星号和条形,而不是组合和排列。

从标准星条算法开始,对我以前的工作进行了改进:

def stars_and_bars(star='*', bar='|', star_count=8, bar_count=2):
    if star_count == 0:
        yield (bar,) * bar_count
        return
    if bar_count == 0:
        yield (star,) * star_count
        return
    for left in range(star_count + 1):
        right = star_count - left
        assert right >= 0
        assert left + right == star_count
        for partial in stars_and_bars(star, bar, left, bar_count - 1):
            yield partial + (bar,) + (star,) * right

验证它是否有效:

>>> sandb = stars_and_bars(star_count=3, bar_count=2)
>>> for result in sandb:
...     print(''.join(result))
... 
||***
|*|**
*||**
|**|*
*|*|*
**||*
|***|
*|**|
**|*|
***||

如您所见,这会产生星和条的每种可能排列。 有8个星和两个小节,我们可以使用它来查找数字和字母的所有可能排列。 然后,我们将其传递给itertools.product()

def combos():
    letters = 'ABCDEF'
    numbers = '1234567890'
    argument_combos = stars_and_bars(numbers, letters)
    for args in argument_combos:
        yield from itertools.product(*args)

结果将完全符合OP的要求。

好吧,这只是从0x0到0x10000000000的十六进制数。 不幸的是,这是十进制的〜1.75e13,因此,如果每个字符为1个字节,每个字符串为10个字符,则不过滤您的two.txt,则大小为175TB。

不过,一旦您想到了这种方式,就应该有某种方法,可以通过一些简单的模运算来快速剔除列表中的大部分内容,这将是我的选择。

我赞成Kevin 的第二个回答 ,但我仍然对他的stars_and_bars实现有点过头了……这是我的看法

噢,我,复制和粘贴错误...一位大括号向下移了一行...

 
 
 
  
  $ cat starbar.py from itertools import combinations as _ic_ def sb(s, ns, b, nb): l = list(range(nb+ns) ---------------V return ([b if i in k else s for i in l)]for k in _ic_(l, nb))
 
  

现在这是正确的版本

$ cat starbar.py
from itertools import combinations as _ic_
def sb(s, ns, b, nb):
    l = list(range(nb+ns))
    return ([b if i in k else s for i in l] for k in _ic_(l, nb))

或者,如果您喜欢冗长的名称,

from itertools import combinations
def stars_and_bars(star, number_of_stars, bar, number_of_bars):
    possible_positions = list(range(number_of_bars + number_of_stars))
    return ([bar if i in combination else star for i in l]
            for combination in combinations(possible_positions, number_of_bars))

以及它是如何工作的? 修正想法,例如ns, nb = 2, 3并查看itertools.combination完成的工作

>>> list(itertools.combinations(range(ns+nb),nb))
[(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]

您可以在[0,1,2,3,4]中使用3个不同数字的所有可能的有序选择进行迭代,这时很容易返回包含正确的星号和条形序列的列表

>>> from starbar import sb
>>> for s_b in sb('*',2, '|',3): print ''.join(s_b)
...
|||**
||*|*
||**|
|*||*
|*|*|
|**||
*|||*
*||*|
*|*||
**|||
>>> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM