Если вы не хотите использовать itertools
, вы, безусловно, можете сделать это с помощью рекурсии, которая будет работать с паролями любой (разумной) длины - она не привязана к трем символам. По сути, каждый рекурсивный вызов будет пытаться добавить новый символ из вашего алфавита к вашему текущему значению догадки. Базовый случай - это когда догадка достигает той же длины, что и искомое значение, и в этом случае вы проверяете соответствие. Если совпадение найдено, верните признак того, что вы добились успеха (я использовал return True
), чтобы вы могли закорачивать любой дальнейший поиск. В противном случае верните сообщение об ошибке (return False
). Использование счетчика global
делает его немного страшнее, но дает те же результаты, о которых вы сообщали.
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def brute_force_guesser(passwd, guess = ''):
global _bfg_counter
if len(guess) == 0:
_bfg_counter = 0
if len(guess) == len(passwd):
_bfg_counter += 1
if guess == passwd:
print('Got "{}" after {} tests'.format(guess, str(_bfg_counter)))
return True
return False
else:
for c in ALPHABET:
if brute_force_guesser(passwd, guess + c):
return True
return False
brute_force_guesser('dog') # => Got "dog" after 2399 tests
brute_force_guesser('doggy') # => Got "doggy" after 1621229 tests
Одним из способов избежать глобального счетчика является использование нескольких возвращаемых значений:
ALPHABET = 'abcdefghijklmnopqrstuvwxyz'
def brute_force_guesser(target, guess = '', counter = 0):
if len(guess) == len(target):
counter += 1
if guess == target:
print('Got "{}" after {} tests'.format(guess, str(counter)))
return True, counter
return False, counter
else:
for c in ALPHABET:
target_found, counter = brute_force_guesser(target, guess + c, counter)
if target_found:
return True, counter
return False, counter
brute_force_guesser('dog') # => Got "dog" after 2399 tests
brute_force_guesser('doggy') # => Got "doggy" after 1621229 tests