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
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