我写了以下代码:
combinationsstring = "List of Combinations"
for a = 0, 65 do
for b = 0, 52 do
for c = 0, 40 do
for d = 0, 28 do
for e = 0, 19 do
for f = 0, 11 do
for g = 0, 4 do
if (((1.15^a)-1)+((20/3)*((1.15^b)-1))
+((100/3)*((1.15^c)-1))+(200*((1.15^d)-1))
+((2000/3)*((1.15^e)-1))+((8000/3)*((1.15^f)-1))
+((40000/3)*((1.15^g)-1))) < 10000 then
combinationsstring = combinationsstring
.."\n"..a..", "..b..", "..c..", "..d
..", "..e..", "..f..", "..g
end
end
end
end
end
end
end
end
local file = io.open("listOfCombinations.txt", "w")
file:write(combinationsstring)
file:close()
我需要找到符合以下等式的所有数据集
(((1.15^a)-1)+((20/3)*((1.15^b)-1))+
((100/3)*((1.15^c)-1))+(200*((1.15^d)-1))+
((2000/3)*((1.15^e)-1))+((8000/3)*((1.15^f)-1))+
((40000/3)*((1.15^g)-1))) < 10000
每个变量(a-g)是一个实数。所以我计算了7中每一个的最大值(当所有其他值都为0时,每个变量的最大值)。这些最大值分别为65,52,40,28,19,11和4(62 = a,52 = b等)
所以我创建了7个嵌套的for循环(如上面的代码所示),在中间的块中,我测试了7个值以查看它们是否符合标准,如果是,则将它们添加到字符串中。在代码的最后,程序将在文件上写入并将最终字符串放在包含所有可能的组合中。
该程序运行正常,但在此模拟过程中进行了31亿次计算,并且通过一些测试,我发现我的计算机平均每秒计算3000次。这意味着总模拟时间约为12天5小时。我没有这个时间,所以我花了整个上午简化要测试的等式,删除不必要的代码,这是我的最终结果。
我使用嵌套for循环完成的这个方法是最优化的方法吗?如果是,有没有其他方法可以加快速度,如果没有,你能告诉我另一种方式吗?
P.S。我使用的是Lua,因为它是我最熟悉的语言,但如果您有其他建议/示例,请使用您的语言,我可以尝试为此程序进行优化。
答案 0 :(得分:3)
我不会说lua,但这里有一些建议:
b
开始循环之前,计算并存储1.15^a-1
;也许称之为fooa
。c
开始循环之前,计算fooa+(20/3)*(1.15^b-1)
;也许称之为foob
。foob
至少为10000
,则跳出循环;里面的东西
只会使结果更大。我还要补充说,嵌套循环是一个非常明智的解决方案,并且通过上述修改,正是我要做的。
答案 1 :(得分:2)
我会推荐一种静态语言来强制执行这种性质的东西。我遇到了一个问题(this one),我在使用python时遇到了问题,但是C ++暴力8-for-loop方法在30秒内计算出解决方案。
答案 2 :(得分:0)
既然您还要求使用不同语言的解决方案,这里有一个快速而肮脏的C ++程序,也包含了@tmyklebu的建议。
#include <iostream>
#include <fstream>
#include <cmath>
int main()
{
std::ofstream os( "listOfCombinations.txt" );
using std::pow;
for( double a = 0; a <= 65; ++a ) {
double aa = (pow(1.15, a) - 1);
if ( aa > 10000 ) break;
for( double b = 0; b <= 52; ++b ) {
double bb = aa + (20/3) * (pow(1.15, b) - 1);
if ( bb > 10000 ) break;
for( double c = 0; c <= 40; ++c ) {
double cc = bb + (100/3) * (pow(1.15, c) - 1);
if ( cc > 10000 ) break;
// The following line provides some visual feedback for the
// user about the progress (it prints current a, b, and c
// values).
std::cout << a << " " << b << " " << c << std::endl;
for( double d = 0; d <= 28; ++d ) {
double dd = cc + 200 * ( pow(1.15, d) - 1);
if ( dd > 10000 ) break;
for( double e = 0; e <= 19; ++e ) {
double ee = dd + (2000/3) * (pow(1.15, e) - 1);
if ( ee > 10000 ) break;
for( double f = 0; f <= 11; ++f ) {
double ff = ee + (8000/3) * (pow(1.15, f) - 1);
if ( ff > 10000 ) break;
for( double g = 0; g <= 4; ++g ) {
double gg = ff + (40000/3) * (pow(1.15, g) - 1);
if ( gg >= 10000 ) break;
os << a << ", " << b << ", "
<< c << ", " << d << ", "
<< e << ", " << f << ", "
<< g << "\n";
}
}
}
}
}
}
}
return 0;
}
答案 3 :(得分:0)
local res={}
combinationsstring = "List of Combinations"
--for a = 0, 65 do
a=0
for b = 0, 52 do
for c = 0, 40 do
for d = 0, 28 do
for e = 0, 19 do
for f = 0, 11 do
for g = 0, 4 do
if (((1.15^a)-1)+((20/3)*((1.15^b)-1))
+((100/3)*((1.15^c)-1))+(200*((1.15^d)-1))
+((2000/3)*((1.15^e)-1))+((8000/3)*((1.15^f)-1))
+((40000/3)*((1.15^g)-1))) < 10000 then
res[#res+1]={a,b,c,d,e,f,g}
end
end
end
end
end
end
end
--end
在我的机器上运行30秒,并填充大约1 GB的内存。你不能在32位Lua VM中放置66倍,而在64位LuaVM中,表的数组部分仍然限制为32位整数键。
我评论了最外圈,所以你需要大约30s * 66 = 33min。我可能会把它写成66个不同的文件。结果首先保存在表格中,然后可以连接起来。退房:
local res={
{1,2,3,4,5,6,7},
{8,9,10,11,12,13,14}
}
for k,v in ipairs(res) do
-- either concatenate each line and produce a huge string
res[k]=table.concat(v,", ")
-- or write each line to a file in this loop
end
local text=table.concat(res,"\n")
print(text)
印刷
1, 2, 3, 4, 5, 6, 7
8, 9, 10, 11, 12, 13, 14