优化强力数值求解器python的建议

2024-06-16 11:50:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道其他一些类似的线程,但我不确定如何将它们应用到我的示例中。在

我试图从蛮力算法攻击倒计时数字游戏。这是我第一次尝试这样的事情,所以有什么关于如何加快这个过程的提示?在

我正在测试它的情况下,答案是无法解决的给定的初始数字。这最终将与一个tkinter接口配对,为整个游戏。在

结构应该是这样的,我们尝试abcdef的每一个命令和op1-5的每个操作组合

from datetime import datetime
import itertools
import math

starttime = datetime.now()
def permutationG(input, s):
    if len(s) == len(input): yield s
    for i in input:
        if i in s: continue
        s=s+i
        for x in permutationG(input, s): yield x
        s=s[:-1]
def op(operator, number1,number2):
    string=str(number1)+str(operator)+str(number2)
    return eval(string)

a=11
b=10
c=9
d=8
e=7
f=6

targetnumber = 101234

listofnumbers = ['a','b','c','d','e','f']
listprep = ['+','-','*','/']
stringofnumbers = ''.join(str(e) for e in listofnumbers)


numberlocations =[]

for item in permutationG(listofnumbers,''):
    numberlocations.append(item)
numberlocations = set(numberlocations)

myarray = itertools.combinations_with_replacement(listprep, 5)
operatorlist = []
for item in myarray:
    #for all different numbers find the different permutations
    temp = list(itertools.permutations(item))
    operatorlist.extend(temp)
#remove duplicates
finaloplist = list(set(operatorlist))

dist=[math.inf]
currentclosestnumber = 0
count=0
looptime=datetime.now()
print('Starting Loop')

for item in numberlocations:
    for ops in finaloplist:
        initial_value = op(ops[0],item[0],item[1])
        for i in range(2,len(item)):
            intcheck2 = int(initial_value) - initial_value
            if initial_value != targetnumber and initial_value >= 0 and intcheck2 == 0:
                newvalue = op(ops[i-1], initial_value, item[i])
            else:
                break
            initial_value = newvalue
        attempt = initial_value
        intcheck = int(attempt) - attempt
        distance = targetnumber - initial_value
        if abs(distance) < abs(dist[0]) and intcheck == 0:
            currentclosestnumber = attempt
            dist[0]=distance
            print(attempt)
        if targetnumber == attempt:
            break
    if targetnumber == attempt:
        break

endtime = datetime.now()
stringtime= endtime-starttime
#print('Loops:    ', count)

if targetnumber == attempt:
    print('FOUNDIT!! Target Number = %s     Closest Number = %s        Time Elapsed = %s' %(targetnumber, currentclosestnumber, stringtime))
elif targetnumber!=attempt:
    print('Heres how close: Target Number = %s     Closest Number = %s        Time Elapsed = %s' %(targetnumber, currentclosestnumber, stringtime))

这将输出大约一分半钟的时间。在

在最后一个计算方法中,使用eval的方法来显示另一个表达式,而不是使用eval的方法。在

任何指导都是非常感谢的。在


注意:我用最新版本的代码编辑了这篇文章。这将计算时间从1:30减少到0:45。主要的改变不是我为每个连续操作创建了一个for循环的长串计算,并使用if语句来确保如果当前值为负数或十进制数,它将中断。在

这大大减少了所需的计算数量。在


Tags: innumberforinputdatetimeifvalueitem
1条回答
网友
1楼 · 发布于 2024-06-16 11:50:39

这是一个较慢的版本,但没有错误。在

我没有时间尝试优化,但我的想法是,大部分问题是在拆分子集时创建/销毁垃圾。在

如果我真的想让它更快,我想你可以使用动态编程方法。在

def subset_splits (a_list):
    if 0 == len(a_list):
        yield ([], [])
    else:
        for sublist1, sublist2 in subset_splits(a_list[1:]):
            yield ([a_list[0]] + sublist1, sublist2)
            yield ([a_list[0]] + sublist2, sublist1)

def reachable (numbers):
    if 1 == len(numbers):
        yield (numbers[0], numbers[0])
    else:
        for list1, list2 in subset_splits(numbers):
            if 0 == len(list2):
                continue
            for x1, expr1 in reachable(list1):
                for x2, expr2 in reachable(list2):
                    yield x1+x2, (expr1, '+', expr2)
                    yield x1*x2, (expr1, '*', expr2)
                    yield x1-x2, (expr1, '-', expr2)
                    yield x2-x1, (expr2, '-', expr1)
                    if 0 != x2:
                        yield x1/x2, (expr1, '/', expr2)
                    if 0 != x1:
                        yield x2/x1, (expr2, '/', expr1)

numbers = [1, 2, 3, 4, 5, 6]
target = 10000

best = numbers[0]
if best == target:
    print(("Answer: ", numbers[0], numbers[0]))
else:
    print(("Best: ", numbers[0], numbers[0]))
    done = False;
    for s, t in subset_splits(numbers):
        if done:
            break

        for x, expr in reachable(s):
            if x == target:
                print(("Answer: ", x, expr))
                done = True
                break
            elif abs(target-x) < abs(target-best):
                print(("Best: ", x, expr))
                best = x

        if done:
            break


        for x, expr in reachable(t):
            if x == target:
                print(("Answer: ", x, expr))
                done = True
                break
            elif abs(target-x) < abs(best-x):
                print(("Best: ", x, expr))
                best = x

相关问题 更多 >