Python 如何在不使用递归的情况下确定一组整数的和

Python 如何在不使用递归的情况下确定一组整数的和,python,nested-loops,Python,Nested Loops,这是我关于堆栈溢出的第一篇文章,我希望这是一篇好文章 这是我自己想出来的一个问题,现在我有点不好意思说,但它把我的生活打得精疲力竭。请注意,这不是一个家庭作业,童子军的荣誉 基本上,程序接受(作为输入)由0到9的整数组成的字符串 strInput = '2415043' 然后你需要把那串数字分成更小的数字组,直到最后,这些数字组的总和给你一个预定义的总数。 对于上述字符串,目标是289 iTarget = 289 对于本例,有两个正确答案(但很可能只显示一个,因为一旦达到目标程序就会停止):

这是我关于堆栈溢出的第一篇文章,我希望这是一篇好文章

这是我自己想出来的一个问题,现在我有点不好意思说,但它把我的生活打得精疲力竭。请注意,这不是一个家庭作业,童子军的荣誉

基本上,程序接受(作为输入)由0到9的整数组成的字符串

strInput = '2415043'
然后你需要把那串数字分成更小的数字组,直到最后,这些数字组的总和给你一个预定义的总数。 对于上述字符串,目标是289

iTarget = 289
对于本例,有两个正确答案(但很可能只显示一个,因为一旦达到目标程序就会停止):

答案2=241,5,0,43(241+5+0+43=289)

请注意,整数不会改变位置。它们仍然与原始字符串中的顺序相同

现在,我知道了如何使用递归来解决这个问题。但令人沮丧的是,我不允许使用递归。

这需要只使用“while”和“for”循环来解决。显然列表和函数也可以

以下是我目前掌握的一些代码:

我的代码:

                                         #Pre-defined input values, for the sake of simplicity
lstInput = ['2','4','1','5','0','4','3'] #This is the kind of list the user will input
sJoinedList = "".join(lstInput)          #sJoinedList = '2415043'
lstWorkingList = []                      #All further calculuations are performed on lstWorkingList
lstWorkingList.append(sJoinedList)       #lstWorkingList = ['2415043']
iTarget = 289                            #Target is pre-defined
while SumAll(lstWorkingList) != iTarget:      #While Sum != 289
    if(len(lstWorkingList[0]) == iMaxLength): #If max possible length of first element is reached
        AddComma(lstWorkingList)              #then add a new comma / group and
        Reset(lstWorkingList)                 #reset all the commas to the beginning of the list to start again
    else:
        ShiftGroups()                         #Keep shifting the comma's until all possible combinations
                                              #for this number of comma's have been tried
                                              #Otherwise, Add another comma and repeat the whole process
[2415043]  #Element 0 has reached maximum size, so add another group 
#AddComma()
#Reset()
[2, 415043] #ShiftGroups()
[24, 15043] #ShiftGroups()
[241, 5043] #ShiftGroups()
#...etc...etc...
[241504, 3] #Element 0 has reached maximum size, so add another group
#AddComma()
#Reset()
[2, 4, 15043] #ShiftGroups()
[2, 41, 5043] #ShiftGroups()
#etc...etc...

[2, 41504, 3] #Tricky part
-

-

呸!那真是太多了

我已经完成了程序将在一张纸上完成的过程,因此以下是预期输出:

输出:

                                         #Pre-defined input values, for the sake of simplicity
lstInput = ['2','4','1','5','0','4','3'] #This is the kind of list the user will input
sJoinedList = "".join(lstInput)          #sJoinedList = '2415043'
lstWorkingList = []                      #All further calculuations are performed on lstWorkingList
lstWorkingList.append(sJoinedList)       #lstWorkingList = ['2415043']
iTarget = 289                            #Target is pre-defined
while SumAll(lstWorkingList) != iTarget:      #While Sum != 289
    if(len(lstWorkingList[0]) == iMaxLength): #If max possible length of first element is reached
        AddComma(lstWorkingList)              #then add a new comma / group and
        Reset(lstWorkingList)                 #reset all the commas to the beginning of the list to start again
    else:
        ShiftGroups()                         #Keep shifting the comma's until all possible combinations
                                              #for this number of comma's have been tried
                                              #Otherwise, Add another comma and repeat the whole process
[2415043]  #Element 0 has reached maximum size, so add another group 
#AddComma()
#Reset()
[2, 415043] #ShiftGroups()
[24, 15043] #ShiftGroups()
[241, 5043] #ShiftGroups()
#...etc...etc...
[241504, 3] #Element 0 has reached maximum size, so add another group
#AddComma()
#Reset()
[2, 4, 15043] #ShiftGroups()
[2, 41, 5043] #ShiftGroups()
#etc...etc...

[2, 41504, 3] #Tricky part
现在是棘手的部分。 在下一步中,第一个元素必须变为24,另外两个元素必须重置

#Increase Element 0
#All other elements Reset() 
[24, 1, 5043] #ShiftGroups()
[24, 15, 043] #ShiftGroups()
#...etc...etc

[24, 1504, 3]
#Increase Element 0
#All other elements Reset()
[241, 5, 043] #BINGO!!!!
好的。这是程序逻辑的基本流程。现在我唯一需要弄清楚的是,如何让它在没有递归的情况下工作

对于那些一直阅读到这一点的人,我真诚地感谢你们,并希望你们仍然有精力帮助我解决这个问题。 如果有什么不清楚的地方,请询问,我会澄清(可能是极其详细的X-D)

再次感谢

编辑日期:2011年9月1日

感谢大家的回应和回答。它们都很好,而且肯定比我走的路线更优雅。 然而,我的学生从未使用过“导入”或任何比列表更高级的数据结构。然而,他们知道很多列表函数。 我还应该指出,学生们在数学方面很有天赋,他们中的许多人参加过国际数学奥林匹克竞赛。因此,这项任务并不超出 他们的智能,也许只是超出了他们python知识的范围

昨晚我喝了一杯尤里卡!片刻。我还没有实现它,但会在周末完成,然后在这里发布我的结果。这可能有点粗糙,但我认为它会完成工作

很抱歉,我花了这么长时间才回复,我的互联网上限已经达到,我不得不等到1号才能重置。这提醒了我,祝大家春天快乐(为你们南半球的人)

再次感谢你的贡献。我会在周末后选择最重要的答案。
问候

要扩展pst的提示,您可以创建一个显式堆栈并使用它来实现递归算法,而不需要实际递归调用任何东西,而不是像递归那样使用调用堆栈。细节留给学生做练习;)

一个能找到所有解决方案的程序可以优雅地表达出来

分割 首先,编写一个函数,以各种可能的方式对字符串进行分区。(以下实现基于。)示例:

谓语 现在,您需要对列表进行筛选,以找到添加到所需值的分区。因此,编写一个小函数来测试分区是否满足此标准:

def pred(target):
   'Returns a function that returns True iff the numbers in the partition sum to iTarget.'
   return lambda partition: target == sum(map(int, partition))
主程序 最后,编写主程序:

strInput = '2415043'
iTarget = 289

# Run through the list of partitions and find partitions that satisfy pred
print filter(pred(iTarget), partitions(strInput))
请注意,结果是在一行代码中计算的


结果:
[['241','5','043'],['241','5','0','43']

递归无论如何都不是执行此任务的最佳工具<代码>itertools.product是

我是这样搜索的:

将搜索空间想象为长度为l的所有二进制字符串,其中l是字符串的长度减去1

取其中一个二进制字符串

将二进制字符串中的数字写在搜索字符串的数字之间

2 4 1 5 0 4 3
 1 0 1 0 1 0
将1变为逗号,将0变为零

2,4 1,5 0,4 3
把这些加起来

2,4 1,5 0,4 3 = 136
是289吗?不。请使用其他二进制字符串重试

2 4 1 5 0 4 3
 1 0 1 0 1 1
你明白了

进入密码

import itertools

strInput = '2415043'
intInput = map(int,strInput)
correctOutput = 289

# Somewhat inelegant, but what the heck
JOIN = 0
COMMA = 1

for combo in itertools.product((JOIN, COMMA), repeat = len(strInput) - 1):
    solution = []
    # The first element is ALWAYS a new one.
    for command, character in zip((COMMA,) + combo, intInput):
        if command == JOIN:
            # Append the new digit to the end of the most recent entry
            newValue = (solution[-1] * 10) + character
            solution[-1] = newValue
        elif command == COMMA:
            # Create a new entry
            solution.append(character)
        else:
            # Should never happen
            raise Exception("Invalid command code: " + command)
    if sum(solution) == correctOutput:
        print solution
编辑: agf发布了代码的另一个版本。它连接字符串,而不是我有点老套的乘10加方法。此外,它使用true和false,而不是我的连接和逗号常量。我想说这两种方法同样好,但我当然有偏见


递归创建了一个隐式堆栈——如何显式地完成它?如果是你自己想出来的,为什么不允许使用递归?你有没有把它用在课堂上做作业?如果你“不允许使用递归”的话,看起来确实是这样。伪匈牙利符号<代码>工作列表?讨厌!我想你是说在
043
中用十进制而不是八进制?这是我使用的同一种方法的更简洁的版本。这不是比实际使用递归更复杂吗?@Nick ODell:当然。既然OP已经告诉了我们这个限制的原因,我们可以看出这不是一个合适的方法。OTOH,如果OP是一个处理任意施加约束的学生(“找到一种不用递归的方法”),这将是一个有效的解决方案;我认为这是最清楚的。您可以进一步简化它(添加分号以显示换行符):
import itertools;strInput='2415043';校正输出=289;用于com
import itertools

strInput = '2415043'
intInput = map(int,strInput)
correctOutput = 289

# Somewhat inelegant, but what the heck
JOIN = 0
COMMA = 1

for combo in itertools.product((JOIN, COMMA), repeat = len(strInput) - 1):
    solution = []
    # The first element is ALWAYS a new one.
    for command, character in zip((COMMA,) + combo, intInput):
        if command == JOIN:
            # Append the new digit to the end of the most recent entry
            newValue = (solution[-1] * 10) + character
            solution[-1] = newValue
        elif command == COMMA:
            # Create a new entry
            solution.append(character)
        else:
            # Should never happen
            raise Exception("Invalid command code: " + command)
    if sum(solution) == correctOutput:
        print solution
import itertools
strInput = '2415043'
correctOutput = 289
for combo in itertools.product((True, False), repeat = len(strInput) - 1):
    solution = []
    for command, character in zip((False,) + combo, strInput):
        if command:
            solution[-1] += character
        else:
            solution.append(character)
            solution = [int(x) for x in solution]
        if sum(solution) == correctOutput:
            print solution