猜一个包含大写字母、小写字母和数字(任意顺序)的 3 个字母的字符串

Guess a 3 letter string that contains an uppercase, lowercase and number (in any order)

我是 Python 的新手,我正在制作一个程序,我们收到一个 3 个字母的长字符串,其中包含一个大写字母、一个小写字母和一个任意给定顺序的数字。然后程序应该通过暴力攻击找到它。

我尝试通过 for 循环执行此操作,并将大写字母、小写字母和字母定义为字符串,然后尝试使用 for 循环遍历这些字母,并尝试将我们想要查找的字符串中的字母与那些字母进行匹配在相应的大写、小写或数字中。

我尝试做的事情:

uppers="ABCDEFGHIJ"
lowers="abcdefghij"
numbers="1234567890"
secret="Je1" #The string the computer is supposed to find through a brute-force attack 

password = ""
counter = 0

for upper in uppers:
    if upper in secret:
        password += upper
        break
    else:
        counter += 1

for lower in lowers:
    if lower in secret:
        password += lower
        break
    else:
        counter += 1

for number in numbers:
    if number in secret:
        password += number
        break
    else:
        counter += 1

print(password)
print("Counter: {0}".format(counter))

当我 运行 代码时,它确实有效,但只有当 secret 字符串的顺序不同于大写、小写和数字的顺序时,("Je1" 有效,"eJ1" 无效)。如果不相应地重新安排 for 循环,该程序就不会真正正确地执行其功能。

非常感谢任何帮助!

以下程序效率稍低,但适合您的目的。

import re
def m(secret):
    import re
    if len(secret)==3 and re.search(r'[A-Z]', secret) and re.search(r'[a-z]', secret) and re.search(r'[0-9]', secret):
        print "Yes"
    else:
        print "No"

可以使用 positive lookaheads 进一步修改,如 Match regex in any order

的已接受答案中所述
if re.search(r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{3}$", secret):
    print "Yes"
else:
    print "No"

您正在按上、下、数字的顺序循环,因此您只能匹配特定顺序的字符串。您需要循环上、下、数字的所有可能排列。也就是说,您需要重复您对这些排列所做的操作:

上,数,下
下、上、数
下,数字,上
数字、下限、上限
数字,上,下

您可以这样缩短三个循环:

for upper in uppers:
    for lower in lowers:
        for number in numbers:
            password = upper + lower + number
            if password == secret:
                print('Matched. Secret is', secret)

通过改变上、下、数字的顺序,再重复五次。

或者,您可以使用 itertools 包来避免循环多次。

from itertools import permutations

for upper in uppers:
    for lower in lowers:
        for number in numbers:
            perms = list(permutations([upper, lower, number]))
            if tuple(secret) in perms:
                print('Matched. Secret is', secret)

无论输入是什么,您的代码都非常明确地始终按此顺序输出大写字母、小写字母和数字。

这可以通过多种方式解决,每种方式都需要权衡取舍。

最简单的就是真正地进行暴力破解,即在每个位置检查所有三个集合。

作为优化,您可以从后续迭代中删除找到匹配项的类别,从而减少搜索 space。这不太可能扩展到现实世界的问题,其中搜索 space 更复杂(您不知道任何一个类别中是否会出现一个或多个字符,除非一个类别不是尚未证明接近字符串的末尾)。

或者,您可以记住在特定类别中的哪个位置找到了一个字符,并在末尾使用此信息以正确的顺序重新组合密码。从某种意义上说,这是最优雅的修复,但同样,它也有一个问题,即它在现实世界的密码破解程序中不是很有用。

所以换句话说,"full brute force" 解决方案是最具可扩展性的,因为它可以扩展到现实世界的问题,尽管它在计算上的可扩展性最低。

展望未来,考虑如何在搜索中枚举所有可能的密码 space,以便每个候选密码都有一个可预测的索引,然后循环遍历该枚举。

在 Python 中实现此目的的一种简单方法是使用 itertools.permutations。这为您提供了给定项目集合的所有可能组合。

在您的例子中,"collection of items" 是所有小写字母、大写字母和数字。所以要使用 permutations 你需要把它们放在一个集合中。为此,您可以将字符串连接在一起:

chars = uppers + lowers + numbers

或者简单地将它们定义为一个字符串:

chars = "ABCDEFGHIJabcdefghij1234567890"

然后你可以 运行 permutations(chars, 3) 这给你长度为 3 个字符的项目作为一个元组。一个例子是 ('a', 'C', '3')。您需要将其与密码字符串进行比较。您可以将密码字符串拆分成一个元组(需要完成一次),或者将置换元组连接成一个字符串(需要为每个项目完成)。在你的例子中,我假设你想将生成的密码用于某些事情,所以让我们将元组连接到一个字符串中,这为我们提供了以下代码:

from itertools import permutations

uppers="ABCDEFGHIJ"
lowers="abcdefghij"
numbers="1234567890"

secret="Je1"

for candidate in permutations(uppers + lowers + numbers, 3):
    if ''.join(candidate) == secret:
        print(candidate)