I am using Euler problems to test my understanding as I learn Python 3.x. After I cobble together a working solution to each problem, I find the posted solutions very illuminating and I can "absorb" new ideas after I have struggled myself. I am working on Euler 024 and I am trying a recursive approach. Now, in no ways do I believe my approach is the most efficient or most elegant, however, I successfully generate a full set of permutations, increasing in value (because I start with a sorted tuple) - which is one of the outputs I want. In addition, in order to find the millionth in the list (which is the other output I want, but can't yet get) I am trying to count how many there are each time I create a permutation and that's where I get stuck. In other words what I want to do is count the number of recursive calls each time I reach the base case, i.e. a completed permutation, not the total number of recursive calls. I have found on * some very clear examples of counting number of executions of recursive calls but I am having no luck applying the idea to my code. Essentially my problems in my attempts so far are about "passing back" the count of the "completed" permutation using a return statement. I think I need to do that because the way my for loop creates the "stem" and "tail" tuples. At a high level, either I can't get the counter to increment (so it always comes out as "1" or "5") or the "nested return" just terminates the code after the first permutation is found, depending on where I place the return. Can anyone help insert the counting into my code?
在学习Python 3.x时,我使用了Euler问题来测试我的理解。在我对每一个问题都做了一个有效的解决方案之后,我发现那些发布的解决方案很有启发性,在我自己挣扎之后,我可以“吸收”新的想法。我正在研究Euler 024,我正在尝试一个递归方法。现在,我绝不相信我的方法是最有效或最优雅的,然而,我成功地生成了一组完整的排列,增加了值(因为我以一个已排序的元组开始)——这是我想要的输出之一。此外,为了在列表中找到第100万个(这是我想要的其他输出,但还不能得到),我正在计算每次创建一个置换的时候有多少个,这就是我被卡住的地方。换句话说,我要做的是计算每次到达基本情况时递归调用的次数,即一个完整的置换,而不是递归调用的总数。我在*上找到了一些非常清楚的例子,计算递归调用的执行次数,但是我没有把这个想法应用到我的代码中。从本质上来说,我在尝试中遇到的问题是使用返回语句“传回完成的”排列的计数。我认为我需要这样做,因为我的for循环创建了“stem”和“tail”元组。在高级别上,要么我无法得到计数器的增量(因此它总是以“1”或“5”的形式出现),或者“嵌套返回”只是在找到第一个排列后终止代码,这取决于我将返回的位置。有人能帮忙把计数插入我的代码吗?
First the "counting" code I found in SO that I am trying to use:
首先,我找到的“计数”代码,我正在尝试使用:
def recur(n, count=0):
if n == 0:
return "Finished count %s" % count
return recur(n-1, count+1)
print(recur(15))
Next is my permutation code with no counting in it. I have tried lots of approaches, but none of them work. So the following has no "counting" in it, just a comment at which point in the code I believe the counter needs to be incremented.
下面是我的排列代码,没有计算。我尝试了很多方法,但没有一个管用。因此,下面的内容没有“计数”,只是在代码中某个点的注释,我相信计数器需要递增。
#
# euler 024 : Lexicographic permutations
#
import time
startTime= time.time()
#
def splitList(listStem,listTail):
for idx in range(0,len(listTail)):
tempStem =((listStem) + (listTail[idx],))
tempTail = ((listTail[:idx]) + (listTail[1+idx:]))
splitList(tempStem,tempTail)
if len(listTail) ==0:
#
# I want to increment counter only when I am here
#
print("listStem=",listStem,"listTail=",listTail)
#
inStem = ()
#inTail = ("0","1","2","3","4","5","6","7","8","9")
inTail = ("0","1","2","3")
testStem = ("0","1")
testTail = ("2","3","4","5")
splitList(inStem,inTail)
#
print('Code execution duration : ',time.time() - startTime,' seconds')
Thanks in advance,
提前谢谢,
Clive
克莱夫。
2 个解决方案
#1
0
Since it seems you've understood the basic problem but just want to understand how the recursion is happening, all you need to do is pass a variable that tells you at what point of the call stack you're in. You can add a 3rd argument to your function, and increment it with each recursive call:
因为看起来您已经理解了基本的问题,但是只是想了解递归是如何发生的,您所需要做的就是传递一个变量,该变量告诉您所处的调用堆栈的位置。您可以向函数添加第三个参数,并在每次递归调用中增加它:
def splitList(listStem, listTail, count):
for idx in range(0,len(listTail)):
...
splitList(tempStem, tempTail, count)
if len(listTail) == 0:
count[0] += 1
print('Count:', count)
...
Now, call this function like this (same as before):
现在,调用这个函数(和之前一样):
splitList(inStem, inTail, [0])
#2
0
Why don't you write generator for this? Then you can just stop on n
th item ("drop while i < n").
为什么不写生成器呢?然后你可以在第n项上停止(“当我< n”时)。
Mine solution is using itertools
, but you can use your own permutations generator. Just yield
next sequence member instead of printing it.
我的解决方案是使用itertools,但是您可以使用自己的per突变生成器。只需生成下一个序列成员而不是打印它。
from itertools import permutations as perm, dropwhile as dw
print(''.join(dw(
lambda x: x[0]<1000000,
enumerate(perm('0123456789'),1)
).__next__()[1]))
#1
0
Since it seems you've understood the basic problem but just want to understand how the recursion is happening, all you need to do is pass a variable that tells you at what point of the call stack you're in. You can add a 3rd argument to your function, and increment it with each recursive call:
因为看起来您已经理解了基本的问题,但是只是想了解递归是如何发生的,您所需要做的就是传递一个变量,该变量告诉您所处的调用堆栈的位置。您可以向函数添加第三个参数,并在每次递归调用中增加它:
def splitList(listStem, listTail, count):
for idx in range(0,len(listTail)):
...
splitList(tempStem, tempTail, count)
if len(listTail) == 0:
count[0] += 1
print('Count:', count)
...
Now, call this function like this (same as before):
现在,调用这个函数(和之前一样):
splitList(inStem, inTail, [0])
#2
0
Why don't you write generator for this? Then you can just stop on n
th item ("drop while i < n").
为什么不写生成器呢?然后你可以在第n项上停止(“当我< n”时)。
Mine solution is using itertools
, but you can use your own permutations generator. Just yield
next sequence member instead of printing it.
我的解决方案是使用itertools,但是您可以使用自己的per突变生成器。只需生成下一个序列成员而不是打印它。
from itertools import permutations as perm, dropwhile as dw
print(''.join(dw(
lambda x: x[0]<1000000,
enumerate(perm('0123456789'),1)
).__next__()[1]))