Python 如何创建任意数量的嵌套循环?

Python 如何创建任意数量的嵌套循环?,python,python-3.x,loops,recursion,Python,Python 3.x,Loops,Recursion,我正在尝试编写一个程序,在匹配特定字符串之前测试所有可能的字符串,并给出尝试次数。举个例子: a = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: '

我正在尝试编写一个程序,在匹配特定字符串之前测试所有可能的字符串,并给出尝试次数。举个例子:

a = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm',
     13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y',
     25: 'z'}

word = 'bike'

found = False
counter = 0
for i in range(len(a)):
    for j in range(len(a)):
        for k in range(len(a)):
            for m in range(len(a)):
                string = f'{a[i]}{a[j]}{a[k]}{a[m]}'
                counter += 1
                print(string, counter)
                if string == word:
                    found = True
                    break
            if found:
                break
        if found:
            break
    if found:
        break

输出结果如下所示:

aaaa 1
aaab 2
aaac 3
aaad 4
aaae 5
aaaf 6
...
bijz 23244
bika 23245
bikb 23246
bikc 23247
bikd 23248
bike 23249
a 1
b 2
c 3
...
aa 27
ab 28
ac 29
...
ba #
bb #
bc #
...
aaa #
aab #
aac #
如果您知道单词将始终为四个字符,则可以使用此代码,但如果您不知道长度,该怎么办?当长度未知时,您将如何创建此项?我试着想想是否有递归函数可以实现这一点,但没有任何结果。我试图实现的程序将有如下输出:

aaaa 1
aaab 2
aaac 3
aaad 4
aaae 5
aaaf 6
...
bijz 23244
bika 23245
bikb 23246
bikc 23247
bikd 23248
bike 23249
a 1
b 2
c 3
...
aa 27
ab 28
ac 29
...
ba #
bb #
bc #
...
aaa #
aab #
aac #

这应该行得通;您可以在的
repeat
参数中输入长度,同时枚举单词(默认情况下从
0
开始;您可以根据需要添加
start=1
):

它输出:

...
bikb 23245
bikc 23246
bikd 23247
bike 23248

如果您只对该数字感兴趣,可以将该单词翻译成以26为基数的数字,并使用以下方法进行转换:

它将单词
bike
转换为以26为底(
18a4
)的数字表示形式,然后可以将其转换为整数(
23248

打包成一个函数:

def number(word):
    return int(word.translate(alpha_to_digits), base=26)

您可以使用
itertools.product
(用于嵌套for循环)+
dict.values
(直接循环字母)+
枚举
(从
1开始,获取计数器):

输出:

...
...
...
bika 23245
bikb 23246
bikc 23247
bikd 23248
bike 23249
注意:这个答案中的所有函数返回23248作为“bike”的答案,因为我喜欢从0开始计数。如果您喜欢从1开始计数,并且想要得到23249的答案,那么只需在函数中的某个位置添加+1即可

第一个想法:编写自己的
increment\u word
函数: 您可以通过编写计算下一个单词的函数来迭代单词。例如,
bikd
后面的下一个单词应该是
bike
,而
cdzz
后面的下一个单词应该是
ceaa

字符串在python中是不可变的,因此为了方便起见,我们将使用字符列表而不是字符串

定义增量字(w): i=len(w)-1 而(w[i]=“z”): w[i]=“a” i=i-1 w[i]=chr(ord(w[i])+1)
请注意,只有在对至少包含一个非“z”字母的单词调用时,此函数才能保证工作。这取决于用户是否要求在
'zzz'
之后输入下一个单词

现在我们可以解决您的问题:

def find_word(w):
候选者=['a'代表w中的[uuu]
w=列表(w)
尝试次数=0
当候选人!=w:
增量字(候选)
尝试次数+=1
返回尝试次数
第二个想法:使用
itertools.product
一般来说,当您想在python中迭代复杂的东西时,有人已经完全编写了您需要的循环构造,并且它在
itertools
包中。如果不是,那么可能是在里面

在这种情况下,您可以使用:

从字符串导入ascii\u小写
来自itertools进口产品
def查找单词(w):
对于计数尝试,枚举中的候选项(乘积(*[ascii\U小写]*len(w)):
如果全部(x==y表示x,zip中的y(w,候选者)):
返回尝试次数
注意我们是如何使用
string.ascii_lowercase
而不是自己输入整个字母表的。有人好心地教python字母表。没有必要过于热心,自己重写字母表(冒着忘记一个字母和破坏一切的风险)

第三个想法:使用递归而不是迭代 任何类型的复杂循环都可以使用递归进行模拟。请注意,python对于递归来说是一种非常糟糕的语言——特别是,python中的递归函数往往非常慢;更不用说,如果递归太深,程序可能会崩溃,因为python没有优化尾部调用。但是,如果您需要使用python以外的语言,则应该考虑此选项

def find_单词(word):
返回find_word_aux(单词'a'*len(单词),0)
def查找单词辅助(单词、候选词、尝试次数):
如果候选者==单词:
返回尝试次数
其他:
i、 c=最大值((i,c)表示枚举(候选)中的i,c,如果c!=“z”)
返回find_word_aux(word,候选者[:i]+chr(ord(c)+1)+'a'*(len(word)-i-1),count_尝试次数+1)
请注意,这与
increment\u word
版本极其相似。不幸的是,在我的机器上使用默认python参数时,它只适用于
aaa
bmg
之间的单词。对于
bmh
之后的任何单词,它都会崩溃,出现异常
递归错误:在比较中超过了最大递归深度
。如果您将此代码翻译为优化尾部调用的语言,如OCaml、Haskell或C,那么它将适用于任何单词

第四个想法:使用组合数学立即解决你的问题 您可以尝试使用乘法计算成批的单词,而不是逐个遍历单词。例如,很容易看出有:

  • 26*26*26=26^3=17576
    介于
    aaaa
    azzz
    之间的单词
  • 8*26*26=5408
    介于
    baaa
    bhzz
    之间的单词
  • 10*26=260
    介于
    biaa
    bijz
    之间的单词
  • 5
    bika
    bike
    之间的单词
总计:23249个单词,介于
aaaa
bike
之间

这为我们提供了一个python程序:

def find_word(w):
尝试次数=0
对于枚举(w)中的i,c:
n=ord(c)-ord('a')
尝试次数+=n*26**(len(w)-i-1)
返回尝试次数

请注意,此处的
for
-循环覆盖的是
w
的字符,而不是所有可能的单词;所以我们迭代了4次,而不是23249次。此功能比其他版本快得多。

谢谢。这足以让我开始学习ou
...
...
...
bika 23245
bikb 23246
bikc 23247
bikd 23248
bike 23249