[英]Get a list of numbers that adds up to a number "n" (using repetition of number) - how would one consider the case of using same number multiple times?
def getList(n, input_list, caching_list):
The function should return a list that adds up to a number "n" using numbers from the input_list, given that numbers can be repeated.假设数字可以重复,function 应该返回一个列表,该列表使用 input_list 中的数字加起来为数字“n”。 Looking to use recursion.希望使用递归。
current code:当前代码:
def getList(n, input_list, caching_list):
if n == 0 :
return caching_list
if n < 0 or len(input_list) == 0:
return []
for i in input_list:
if find_sum(n-i,input_list,caching_list) == caching_list:
caching_list.append(i)
return caching_list
return []
example n = 13, input_list= [2,3,5] should result in [2,2,2,2,2,3] or [5,5,2] or anything that adds to 13.例如 n = 13,input_list= [2,3,5] 应该导致 [2,2,2,2,2,3] 或 [5,5,2] 或任何与 13 相加的结果。
Doing this with using a number just 1 time is easy, but how would one consider the case of using same number multiple times?只需使用一个数字 1 次就可以做到这一点,但是如何考虑多次使用相同数字的情况呢?
With recursion, this can be solved using a depth-first search (DFS) algorithm , but it can throw RecursionError: maximum recursion depth exceeded in comparison
使用递归,这可以使用深度优先搜索 (DFS) 算法来解决,但它可以抛出RecursionError: maximum recursion depth exceeded in comparison
def find(n2, plist):
result = []
def find2(n):
if n == 0:
return True
if n < 0:
return False
for p in plist:
if find2(n-p):
result.append(p)
return True
find2(n2)
return result
print(find(17, [2,3,5])) # [3, 2, 2, 2, 2, 2, 2, 2]
print(find(7, [3,5])) # []
print(find(77777, [3,5,7,11])) # recursion error
To get rid of the recursion error, recursive DFS can be rewritten into iterative DFS .为了消除递归错误,可以将 recursive DFS 重写为iterative DFS 。
I find itertools can be very handy for stuff like this.我发现itertools对于这样的东西非常方便。 I am sure there are better ways to do it, but this might get you want you need:我相信有更好的方法可以做到这一点,但这可能会让你想要你需要:
import itertools
def find_sum(n, p_list):
max_len = n // min(p_list)
min_len = n // max(p_list)
for i in range(min_len, max_len+1):
I = itertools.combinations_with_replacement(p_list, i)
for j in I:
if(sum(j) == n):
return(list(j))
return([])
print(find_sum(17,[2,3,5]))
# [2, 5, 5, 5]
print(find_sum(7, [3, 5]))
# []
You could easily alter the code to give you all combinations.您可以轻松更改代码以提供所有组合。
def find_sum(n, p_list):
max_len = n // min(p_list)
min_len = n // max(p_list)
answers = []
for i in range(min_len, max_len+1):
I = itertools.combinations_with_replacement(p_list, i)
for j in I:
if(sum(j) == n):
answers.append(list(j))
return(answers)
find_sum(17,[2,3,5])
#[[2, 5, 5, 5], [2, 2, 3, 5, 5], [3, 3, 3, 3, 5], [2, 2, 2, 3, 3, 5], [2, 3, 3, 3, 3, 3], [2, 2, 2, 2, 2, 2, 5], [2, 2, 2, 2, 3, 3, 3], [2, 2, 2, 2, 2, 2, 2, 3]]
Regarding @dantebarba's comment, I haven't really looked to see how it will scale for large problems and there may be more efficient approaches.关于@dantebarba 的评论,我还没有真正了解它如何扩展以解决大问题,并且可能有更有效的方法。
These 3 lines of code should raise some red flags:这 3 行代码应该引起一些危险信号:
if find_sum(n-i,p,p_list,sum_list) == sum_list:
sum_list.append(i)
return sum_list
You have a recursive function storing its results in sum_list
, modifying it, and also depending on its values for equality checks.您有一个递归的 function 将其结果存储在sum_list
中,对其进行修改,并根据其值进行相等性检查。 This makes your program extremely difficult to reason about.这使您的程序极难推理。 Does the behavior change if you swap the arguments around the equality sign?如果在等号周围交换 arguments,行为会改变吗? I have no idea.我不知道。
In general, your recursive programs should try to avoid passing their result as a parameter.通常,您的递归程序应尽量避免将其结果作为参数传递。 Since that if
statement is really asking whether we can make a certain sum, why not break that into a separate function?既然那个if
语句实际上是在问我们是否可以得到一定的总和,为什么不把它分解成一个单独的 function 呢?
def can_sum(n, p_list, cache={}):
if n in cache:
return cache[n]
if n == 0:
return True
if n < 0:
return False
return any(can_sum(n-p, p_list) for p in p_list)
You want to use some kind of caching (otherwise, your program is exponential-time), and functools.cache
is preferable if you can use outside libraries, but this will do the job.您想使用某种缓存(否则,您的程序是指数时间的),如果可以使用外部库,则functools.cache
更可取,但这可以完成工作。
How should your find_sum
function return results without passing the result as a parameter?你的find_sum
function 应该如何在不将结果作为参数传递的情况下返回结果? Just add your value to the end, exactly like your code did:只需将您的价值添加到最后,就像您的代码一样:
def find_sum(n, p_list):
for p in p_list:
if can_sum(n-p, p_list):
return find_sum(n-p, p_list) + [p]
return []
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.