我想不出一个更好的标题,因为一个合适的标题可能需要完整的解释。此外,组合可能具有误导性,因为问题将涉及排列。
我想要完成的是在以下问题上胜过Python语言中的蛮力方法:给定4个基本操作+,-,*,/和从1到9的数字,以及所有可能的5位数字组合和4个不会导致给定数字(被视为整数)的重复(排列)的操作,如1+5*9-3/7=45,1-2/3+9*5=45,...获得从最低可能值到最高可能值的所有整数,并找出是否空间扩展中的所有整数都存在。
我对暴力的初步尝试如下:
def brute_force(target):
temp = 0
x = [i for i in range(1,10)]
numbers = [str(i) for i in x]
operators = ["+","-","*","/"]
for values in permutations(numbers,5):
for oper in permutations(operators):
formula = "".join(o + v for o,v in zip([""]+list(oper),values))
if round(eval(formula)) == int(target):
temp += 1
if temp > 0:
return True
else:
return False
for i in range(-100,100):
total = brute_force(i)
if total:
print(i)
else:
print(str(i) + 'No')
除了没有找到的整数外,它只打印“No”。显而易见,所有整数值都可以在空间扩展中找到,范围在-71到79之间。
我对Python和算法实现都是一个新手,但我认为该算法的复杂度为O(n!),因为涉及到了排列。但是如果不是这样的话,我仍然想要一个执行得更好的算法(比如递归或动态编程)。
发布于 2020-01-24 08:53:45
让我们只计算一次可能的结果集(以一种更简单、更快的方式):
expression = [None] * 9
results = {eval(''.join(expression))
for expression[::2] in permutations('123456789', 5)
for expression[1::2] in permutations('+-*/')}
在我的笔记本电脑上,它可以在4.5秒内计算出所有可能的结果。像这样重写你的代码需要5.5秒。这两种方法都比你为每个目标整数重做所有计算的方式要快得多。
使用该结果集,我们可以即时回答问题,确认您的范围,并显示仅缺少-70和78:
>>> min(results), max(results)
(-70.71428571428571, 78.83333333333333)
>>> set(range(-70, 79)) - results
{-70, 78}
发布于 2020-01-24 08:15:01
首先,让我们分析一下这个表达式。您有三个术语:乘积P
(A*B)、商Q
(A/B)和标量S
。您可以将这些与加法和减法相结合。
其中两项是正的;另一项是负的,所以我们可以简单地否定三项(P,Q,S)中的一项并求和。这就减少了组合学。
乘法是可交换的;w.l.o.g,我们可以假设A>B,它将排列减半。
以下是我对第一效率的建议:
对于一个开始,这样的改进足够了吗?
感谢Heap Overflow
指出了我错过的数据流案例(这是专业上令人尴尬的:-)。
案例A*B/C+D-E没有在上面介绍。这种方法是可比较的。
碰巧,稍微检查一下较大的情况(除数为1的商)和剩余的各种数字,就会证明该方法将涵盖-8到77 (包括-8到77)范围内的所有整数。您不能从原始的9位数字中删除3个大数字,而不留下其差异忽略了所需间隔的数字。
如果允许您在代码中包含该分析,则可以通过反向搜索来缩短这一部分。您演示了大型案例{48,54,56,63,72}的覆盖范围,演示了较小商数的缺口填充,然后您可以在我的原始帖子中搜索复杂度较低的案例,享受您只需要78,79和小于-8的数字的知识。
发布于 2020-01-24 08:16:42
我认为你只需要找到一次排列。从所有可能的和中创建一个集合。然后再做个查询。仍然有点蛮力,但省去了很多重复的计算。
def find_all_combinations():
x = [i for i in range(1,10)]
output_set = set()
numbers = [str(i) for i in x]
operators = ["+","-","*","/"]
print("Starting Calculations", end="")
for values in permutations(numbers,5):
for oper in permutations(operators):
formula = "".join(o + v for o,v in zip([""]+list(oper),values))
# Add all the possible outputs to a set
output_set.add(round(eval(formula)))
print(".", end="")
return output_set
output = find_all_combinations()
for i in range(-100,100):
if i in output:
print(i)
else:
print(str(i) + 'No')
https://stackoverflow.com/questions/59888690
复制相似问题