列表与特定总和的组合

时间:2017-07-03 13:15:29

标签: python permutation

我想用python解决这个问题:

  

按数字顺序取数字1,2,3到9并加上一个加号   数字之间的符号或减号或两者都不能作出总和   最多可达100个。例如,实现此目的的一种方法是:1 + 2 + 34    - 5 + 67 - 8 + 9 = 100,使用六个加号和减号。你需要做的最少的加分和缺点是什么?

我考虑过从生成有效元组开始,例如(1,2,34,567,89),然后找出哪些加起来为100,然后找出最短的。

为此,我首先创建了一个可能的数字列表,数十和数百,因为我很确定没有4位数的组合。

strnumbers = [str(x) for x in range(1,10)]
digits = [int(i) for i in strnumbers]
tens = [int(strnumbers[a] + strnumbers[a+1]) for a in range(8)]
hundreds = [int(strnumbers[a] + strnumbers[a+1] + strnumbers[a+2]) for a in range(7)]

但是,我不确定如何创建实际可能的列表。

我的问题是双重的:

  1. 您如何使用数十位和数百位来创建可能的元组?

  2. 这在计算方面是否合理?感觉就像我正在创造许多额外的工作

3 个答案:

答案 0 :(得分:3)

import itertools

results = []
for opers in itertools.product(('-','+',''),repeat=8):
    expression = '1{}2{}3{}4{}5{}6{}7{}8{}9'.format(*opers)
    result = eval(expression)
    if result == 100:
        results.append(expression)
best_result = min(results, key=len)
print(best_result, len(best_result)-9)

答案 1 :(得分:2)

这是一种方法,我用于类似的问题。你没有展示足够的代码来展示我的完整解决方案,所以这是一个想法的大纲。这种方法与您的方法不同,但您不必担心每个术语的位数。

  1. 您希望数字按顺序包含在其中的其他字符,因此请考虑字符串'1{}2{}3{}4{}5{}6{}7{}8{}9'
  2. 使用itertools.product()获取使用'+''-'''填充这些大括号的所有可能方法。你需要八个短串。产品总数为3**8 == 6561,这是Python程序的一个小数字。
  3. 对于每种可能的产品,请使用产品上字符串的format()方法创建完整表达式。
  4. 使用eval()计算该表达式的值。使用eval()通常很危险,但由于您只在已构建的字符串上使用它,因此没有问题。
  5. 将值与100进行比较,并存储导致该值的字符串。
  6. 收集所有字符串后,找到长度最短的字符串。那个人将拥有最少的优点和缺点。
  7. 从最短的长度减去9,数字位数,打印出来,然后就完成了。
  8. 可以组合步骤5到7,从而减少内存使用量。使用product作为生成器并在其上循环,而不是从中生成列表,也会降低内存使用率。

答案 2 :(得分:1)

我会以不同的方式处理这个问题。你有你的数字列表:

digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]

因此,你必须做出8个关于如何加入数字的决定(或9,如果允许在1之前加减,但我认为它不在这里)。对于每个决策,您有三种选择:加号,减号或不加号(加入)。因此有3 ^ 8个选择。我会迭代它们找到最好的一个:

from itertools import product

digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]
options = ["", "+", "-"]
number = 100
best_sol_str = ""
best_sol_cost = 10  # Or infinity
for sol in product(*([options] * 8)):  # `* 9` if starting with "-" allowed
    factor = 1
    current = 0
    total = 0
    sol_cost = 0
    sol_str = ""
    # Remove `("",) + ` if used `* 9` before
    for opt, d in zip(("",) + sol, digits):  
        sol_str += opt + str(d)
        if opt == "":
            current = current * 10 + d
        else:
            total += factor * current
            current = d
            sol_cost += 1
            if opt == "+":
                factor = 1
            elif opt == "-":
                factor = -1
    total += factor * current
    if total == number and sol_cost < best_sol_cost:
        best_sol_str = sol_str
        best_sol_cost = sol_cost

print("Best solution: {}={} ({} operations).".format(
    best_sol_str, number, best_sol_cost))