项目Euler#1 - Lasso

时间:2013-09-16 13:12:55

标签: optimization lasso

我一直在研究Project Euler问题,作为学习如何在Lasso中编码的一部分,我想知道我的解决方案是否可以改进。以下是我在Lasso 8代码中问题#1下面的内容,它返回正确的答案:

var ('total' = 0);

loop(1000-1);
    loop_count % 3 == 0 || loop_count % 5 == 0 ? $total += loop_count;
/loop;

output($total);

我的问题:是否有更好或更快的方法对此进行编码?谢谢!

3 个答案:

答案 0 :(得分:1)

实际上Chris看起来我的L9代码答案几乎完全相同。然而,我必须要做的就是将它包裹在一个循环中以计时1000次。

Lasso 9可以做微秒,而之前的版本只能以毫秒为单位。

以下是3种方式 - 第一种是你的,然后是我的两种版本。

define br => '<br>'
local(start_time = micros)
loop(1000)=>{
    var ('total' = 0);

    loop(1000-1);
        loop_count % 3 == 0 || loop_count % 5 == 0 ? $total += loop_count;
    /loop;
    $total;

}
'Avg (L8 code in 9): '+(micros - #start_time)/1000+' micros'

br
br

local(start_time = micros)
loop(1000)=>{
    local(sum = 0)
    loop(999)=>{ loop_count % 3 == 0 || loop_count % 5 == 0 ? #sum += loop_count }
    #sum
}
'Avg (incremental improvement): '+(micros - #start_time)/1000+' micros'

br
br

local(start_time = micros)
loop(1000)=>{
    local(sum = 0)
    loop(999)=>{ not (loop_count % 3) || not(loop_count % 5) ? #sum += loop_count }
    #sum
}
'Avg using boolean not: '+(micros - #start_time)/1000+' micros'

输出结果为:

Avg (L8 code in 9): 637 micros
Avg (incremental improvement): 595 micros
Avg using boolean not: 596 micros

请注意,我没有使用“输出”,因为它在8和许多情况下是多余的,而且完全冗余9:)

答案 1 :(得分:1)

有一个有趣的故事,关于高斯曾经如何总结数字,这涉及一个有助于避免循环的策略。

local('p' = 3);
local('q' = 5);
local('n' = 1000);
local('x' = integer);
local('before');
local('after');

#before = micros

loop(1000) => {
    /* In the tradition of Gauss */
    local('n2' = #n - 1)

    local('pq' = #p * #q)

    local('p2' = #n2 / #p)
    local('q2' = #n2 / #q)
    local('pq2' = #n2 / #pq)

    local('p3' = (#p2 + 1) * (#p2 / 2) + (#p2 % 2 ? #p2 / 2 + 1 | 0))
    local('q3' = (#q2 + 1) * (#q2 / 2) + (#q2 % 2 ? #q2 / 2 + 1 | 0))
    local('pq3' = (#pq2 + 1) * (#pq2 / 2) + (#pq2 % 2 ? #pq2 / 2 + 1 | 0))

    #x = #p * #p3 + #q * #q3 - #pq * #pq3
  }

#after = micros

'Answer: ' + #x + '<br/>\n'
'Average time: ' + ((#after - #before) / 1000) + '<br/>\n'

/* Different numbers */
#p = 7
#q = 11

#before = micros

loop(1000) => {
    /* In the tradition of Gauss */
    local('n2' = #n - 1)

    local('pq' = #p * #q)

    local('p2' = #n2 / #p)
    local('q2' = #n2 / #q)
    local('pq2' = #n2 / #pq)

    local('p3' = (#p2 + 1) * (#p2 / 2) + (#p2 % 2 ? #p2 / 2 + 1 | 0))
    local('q3' = (#q2 + 1) * (#q2 / 2) + (#q2 % 2 ? #q2 / 2 + 1 | 0))
    local('pq3' = (#pq2 + 1) * (#pq2 / 2) + (#pq2 % 2 ? #pq2 / 2 + 1 | 0))

    #x = #p * #p3 + #q * #q3 - #pq * #pq3
  }

#after = micros

'Answer: ' + #x + '<br/>\n'
'Average time: ' + ((#after - #before) / 1000) + '<br/>\n'

输出结果为:

Answer: 233168<br/>
Average time: 3<br/>
Answer: 110110<br/>
Average time: 2<br/>

虽然我是第一次运行它,但是第一次平均时间是18而不是3.也许Lasso正在为后续运行做一些聪明的事情,或者可能只是运气不好。

答案 2 :(得分:0)

n =输入号码

x = (n-1)/3 = 3个可分割数字的数量。*
sum3 = (3*x*(x+1)) / 2 =这些数字的总和。**

y = (n-1)/5 = 5个可除数的计数。
sum5 = (5*y*(y+1)) / 2 =这些数字的总和。

half_Ans = sum3 + sum5

但是15、30、45 ...计数两次(在sum3sum5中)。
因此将其删除一次,因此只有它们计数一次。

z = (n-1)/15 = 15个可除数的计数。
sum15 = (15*z*(z+1)) / 2 =这些数字的总和。

Answer = half_Ans - sum15

  • * => (n-1)/3给出3个可除数的计数。

    • 如果n = 100我们需要计算(3, 6, 9, ..., 99)
    • 3是第1位,6是第2位,....依此类推99是第33位
    • 所以这些数字的总数是last number / 3
    • 最后一个数字靠近我们的输入n(特别是小于输入n
    • 如果n = 99不能计数99,因为语句“在n 以下找到3或5 的所有倍数之和。”
    • 因此不减去1的最后一个不需要的数字也算在内,如果n可被3整除
  • ** => (3*x*(x+1)) / 2给出这些数字的总和

    • 如果n = 100总和为3 + 6 + 9 + ... + 99
    • 所有组成部分均为3的倍数。
    • 所以3 + 6 + 9 + ... + 99 = 3*(1 + 2 + 3 + ... + 33)
    • 1至m的总和是(m*(m+1)) / 2
    • 所以3 + 6 + 9 + ... + 99 = (3*33*(33+1)) / 2
    • 这里m的{​​{1}}是该序列的最后一个数字或总数 或序列的长度,这就是为什么我们发现可整数的数量的原因。