简体   繁体   English

获取加起来为数字“n”的数字列表(使用数字重复)——如何考虑多次使用相同数字的情况?

[英]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.

相关问题 使用while循环打印偶数n次 - Print even numbers n number of times, using while loop 如何使用多处理获取数字列表中的最大数字 - How to get the greatest number in a list of numbers using multiprocessing 如何使用python在csv文件中重复一行n次 - how to repeat a row n number of times in a csv file using python 如何在机器人框架中执行特定的测试用例 n 次 - how to execute a particular test case n number of times in robot framework 如何计算相同数字在python列表中出现的次数? - How to count the number of times same number has appeared in a list in python? 如何检查浮点数列表加起来是否为整数? - How to check if a list of floats adds up to a whole number? 设 n 为平方数。 使用 Python,我们如何有效地计算自然数 y 直到极限 l 使得 n+y^2 又是一个平方数? - Let n be a square number. Using Python, how we can efficiently calculate natural numbers y up to a limit l such that n+y^2 is again a square number? 如何以“ n”次洗牌 - How to shuffle with “n” number of times 如何使用 python 计算文本出现在多个单元格中的次数 - How to count number of times a text appeared in multiple cells using python 如何避免在使用python线程时记录多次 - how to avoid logging multiple number of times while using python threads
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM