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')
我使用 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')