我正在尝试制作能够打印a
到zzz
的所有可能组合的程序。我试图添加一个保存状态功能,它工作正常,但有这个错误。
假设我在打印e
之类的内容时打断了程序。当我再次执行程序时,它会一直运行到z
,但在z
之后而不是打印aa
它会打印ba
并从ba
继续。这也是在它打印zz
之后发生的。它打印baa
而不是aaa
。我该如何解决这个问题?
这是我到目前为止所做的:
import pickle,os,time
alphabet="abcdefghijklmnopqrstuvwxyz"
try:
if os.path.isfile("save.pickle")==True:
with open("save.pickle","rb") as f:
tryn=pickle.load(f)
for i in range(3):
a=[x for x in alphabet]
for j in range(i):
a=[x+i for x in alphabet for i in a]
b=a[tryn:]
for k in b:
print(k)
time.sleep(0.01)
tryn+=1
else:
tryn=0
for i in range(3):
a=[x for x in alphabet]
for j in range(i):
a=[x+i for x in alphabet for i in a]
for k in a:
print(k)
tryn+=1
time.sleep(0.01)
except KeyboardInterrupt:
with open("save.pickle","wb") as f:
pickle.dump(tryn,f)
答案 0 :(得分:2)
如果您使用python2或python3作为标记建议,那么它已存在于标准库中。有关解决此问题的简单方法,请参阅itertools,product py2和product py3。
答案 1 :(得分:1)
你的问题几乎肯定在这里:
a=[x for x in alphabet]
for j in range(i):
a=[x+i for x in alphabet for i in a]
也许您不应该将循环中的值分配给a,而是使用不同的名称?否则,你每次都要改变你在循环中使用的内容......
编辑:更详细。所以,从技术上讲,user2357112的答案更为正确,但我正在修改我的。最初的答案只是快速阅读,所以另一个答案接近原意。但是,原始版本效率低(出于更多原因而不是使用产品:),因为您不止一次地生成内部循环。因此,让我们来看看为什么这是一个坏主意,作为一项教育活动:
初始算法:
for i in range(n):
assign a to alphabet
for j in range(i):
i times, we rewrite a to be all combinations of the current set against the alphabet.
注意,对于此算法,要生成长度(n)乘积,我们必须生成所有先前的乘积长度(n-1),长度(n-2),...,长度(1)。但是你没有拯救那些。
你最好做这样的事情:
sum_list = alphabet[:]
#get a copy
product_list = alphabet[:]
#Are we starting at 0, or 1? In any case, skip the first, since we preloaded it
for i in range(1, n):
# Your existing list comprehension was equivalent here, and could still be used
# it MIGHT be faster to do '%s%s'%(x,y) instead of x+y... but maybe not
# with these short strings
# This comprehension takes the result of the last iteration, and makes the next iteration
product_list = [x+y for x,y in product(product_list, alphabet)]
# So product list is JUST the list for range (n) - i.e. if we are on loop 2, this
# is aaa...zzz. But you want all lengths together. So, as you go, add these
# sublists to a main list.
sum_list.extend(product_list)
总的来说,你的工作量很少。
结合其他事情:
product_list
的当前值)和使它更像生成器,然后它实际上更像是一个真实世界的例子。答案 2 :(得分:1)
for i in range(3):
a=[x for x in alphabet]
for j in range(i):
a=[x+i for x in alphabet for i in a]
b=a[tryn:]
这是你的错误。您跳过每个长度的第一个tryn
字符串,而不仅仅是第一个tryn
字符串。如果不是以下内容,这将更容易在输出中识别:
for k in b:
print(k)
time.sleep(0.01)
tryn+=1
您修改tryn
,即您正在跳过的内容。当您打印出长度为2的字符串时,您跳过的数字等于长度为1的字符串数。当你打印出长度为3的字符串时,你会跳过一些等于长度为2的字符串的数字。如果tryn
大于长度为1的字符串数,则会跳过更多。
答案 3 :(得分:0)
以下是我建议如何在Python中解决此问题。我没有实现保存状态功能;这个序列不是很长,你的计算机应该能够非常快地生成这个序列,所以我认为不值得努力让它干净利落。
import itertools as it
def seq(alphabet, length):
for c in range(1, length+1):
for p in it.product(alphabet, repeat=c):
yield ''.join(p)
alphabet="abcdefghijklmnopqrstuvwxyz"
for x in seq(alphabet, 3):
print(x)
如果你真的想,你可以使用itertools
制作单行。我觉得这很难阅读和理解;我更喜欢上面的版本。但由于使用itertools.chain
和itertools.imap()
而不是Python for
循环,这确实有效并且会更快一些。
import itertools as it
def seq(alphabet, length):
return it.imap(''.join, it.chain.from_iterable(it.product(alphabet, repeat=c) for c in range(1, length+1)))
alphabet="abcdefghijklmnopqrstuvwxyz"
for x in seq(alphabet, 3):
print(x)
在Python 3.x中,您可以使用map()
而不是itertools.imap()
。