2015-06-17 4 views
3

Я пытаюсь сделать генератор строк для bruteforce в Python, а itertools.combinations_with_replacement, похоже, сделал всего лишь трюк.Комбинации python bruteforce с заданной стартовой строкой

gen = itertools.combinations_with_replacement('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',12) 
for combination in gen: 
    check(''.join(combination)) 

Say пользователь запускает программу в течение нескольких часов и доходит до строки aaaeabdouzIU.

Есть ли способ передать строку, где они остановились, чтобы начать делать комбинации с этой точки дальше?

Так что, если я передать строку «acc» он должен начать пытаться «acd», «ace», ...

itertools.combinations_with_replacement не обеспечивает это изначально, есть ли способ, кто-то может achive это?

+0

Я ничего не знаю, но документация itertools содержит эквивалентный фрагмент кода (два, фактически), который вы могли бы попытаться применить к вашему использованию. – Evert

+1

Также бонус лакомый кусочек. Если вы не хотите печатать все буквы. 'import string; string.ascii_letters' – cr1msonB1ade

+0

Вы хотите иметь возможность «увеличивать» первый результат, чтобы получить второй, а n-й - получить n + 1-й. Нет встроенного способа. Попробуйте преобразовать выходной диапазон в целочисленный диапазон и обратно. Если это возможно, вы можете легко увеличивать целые числа, начиная с любого места в последовательности, и генерировать любую подпоследовательность, которую вы желаете. – mehtunguh

ответ

4

Взяв исходный код от itertools man page, скопируйте код для кода комбинаций_with_replace, но замените строку 7 новыми индексами, начиная с введенного слова.

inputStr='acc' 
indices=[pool.index(l) for l in inputStr] 

А затем запустите оставшуюся часть кода с страницы руководства.

EDIT: Для полного бега функции:

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) 
+0

Заключительный блок должен быть непреднамеренным - он принадлежит циклу for, а не if. Код не работает иначе – Magnus

1

Это легко, если вы знаете, учитывая сочетание, как генерировать следующий.

Одним из способов сделать это может быть определение отображения из комбинации в натуральные числа и обратное отображение, от натуральных чисел до комбинаций. Например, вы можете использовать base62_encode/base62_decode от Base 62 conversion

def next_comb(s): 
    return base62_encode(1+base62_decode(s)) 

и генератор, чтобы генерировать все комбинации с учетом отправной точкой:

def generate_all(start='a'): 
    while True: 
     yield start 
     start = next_comb(start) 

Использование:

for comb in generate_all(): 
    print(comb) 

или возобновить вычисление от начальной точки:

for comb in generate_all(starting_point): 
    print(comb)