Python itertools.combinations 从某个值继续?

Python itertools.combinations continue from certain value?

我使用 itertools 生成所有组合或可打印的 ascii 字符:

for combo in product('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;?@[\]^_`{|}~ \t\n\r\x0b\x0c', repeat=10):

但是,脚本被中断了,但我得到了最后一个序列字符串。有没有办法使用这个字符串作为起始序列来继续生成值?谢谢。

UPD:我试图通过暴力破解 XOR 密文来解决一些 CTF 任务。 Xortool 的输出:

 2:   11.2%
   5:   15.6%
   7:   11.2%
  10:   18.4%
  15:   9.6%
  18:   6.6%
  20:   12.1%
  25:   5.8%
  30:   5.5%
  40:   4.0%

我现在看不到其他解决方案,至少会尝试 bf 5 字节密钥。

好的,你看,这个问题真的没有意义,因为你的循环可能 运行 比你的计算机要长,但无论如何我有一个答案!

你的循环产生这样的元组:

('0', '0', '0', '0', '0', '0', '1', 'C', '!', 'D')

假设这是您在上一个 运行 中看到的最后一个。所以像这样写你的代码:

resume_target = ('0', '0', '0', '0', '0', '0', '1', 'C', '!', 'D')
sequence = product(all_those_letters, repeat=10)
for combo in sequence:
    if combo == resume_target:
        break

for combo in sequence:
    # now do whatever you'd normally do

我在这里所做的只是简单地 "fast forward" 通过第一个最少的计算,但是之前已经处理了许多组合。这很简单并且应该是正确的,但它确实假设您对每个组合都做了大量的工作——否则快进是没有意义的,因为您可以再次做一些微不足道的工作。

假设处理的最后一个字符串以字符 '5' 开头。然后你可以忽略所有以前面字符开头的字符串,并像这样设置迭代:

for start in ('567...'):
    for subcombo in product('01234567...', repeat=9):
        yield (start,) + subcombo

然而你真的无法通过这个搜索space。计算总组合数很简单:

>>> len('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;?@[\]^_`{|}~ \t\n\r\x0b\x0c') ** 10
73742412689492826049L

即使你每秒可以处理十亿个组合,你也不会在一年内完成:

>>> 1000000000 * 60 * 60 * 24 * 365
31536000000000000

它可能不快,但使用 itertools.islice 你可以跳过其中的前 n 个:

c = itertools.islice(itertools.product('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;?@[\]^_`{|}~ \t\n\r\x0b\x0c', repeat=10), 5, None)
c.next()
Out[39]: ('0', '0', '0', '0', '0', '0', '0', '0', '0', '5')