Python bruteforce combinations with given starting line
I'm trying to make a bruteforce string generator in Python and itertools.combinations_with_replacement
it seems to only do the trick.
gen = itertools.combinations_with_replacement('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',12)
for combination in gen:
check(''.join(combination))
Tell the user to run the program for hours and reach the line aaaeabdouzIU
.
Is there a way to pass the line where they left off to start making combinations from that point?
So if I pass in the string ' acc
' it should start trying ' acd
', ' ace
',...
itertools.combinations_with_replacement
doesn't foresee this initially, is there a way someone can achieve this?
source to share
Taking the source code from the itertools man page , copy the code for the combination_with_replacement code, but replace line 7 with new indices starting with the word you entered.
inputStr='acc'
indices=[pool.index(l) for l in inputStr]
And then run the rest of the code from the man page.
EDIT: for the complete function:
def combinations_with_replacement(iterable, r, startWord=None):
# combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
pool = tuple(iterable)
n = len(pool)
if not n and r:
return
if startWord is None:
indices = [0] * r
else:
assert len(startWord) == r
indices = [pool.index(l) for l in startWord]
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != n - 1:
break
else:
return
indices[i:] = [indices[i] + 1] * (r - i)
yield tuple(pool[i] for i in indices)
source to share
It's easy if you know, given the combination, how to create the next one.
One way to do this would be to define a mapping from combination to natural numbers and reverse mapping from natural numbers to combinations. For example you can use base62_encode
/ base62_decode
from Convert base 62
def next_comb(s):
return base62_encode(1+base62_decode(s))
and a generator to generate the entire combination with a given starting point:
def generate_all(start='a'):
while True:
yield start
start = next_comb(start)
Using:
for comb in generate_all():
print(comb)
or, to resume the calculation from the starting point:
for comb in generate_all(starting_point):
print(comb)
source to share