2

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

var ('total' = 0);

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

output($total);

我的问题:有没有更好或更快的编码方式?谢谢!

4

3 回答 3

1

实际上,克里斯看起来我的 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 中是完全多余的 :)

于 2013-09-16T15:15:41.723 回答
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 为后续运行做了一些聪明的事情,或者只是运气不好。

于 2013-09-18T05:42:51.047 回答
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... 计数两次(在sum3&中sum5)。
所以删除它一次,所以他们只计算一次。

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(特别是小于 input n
    • 如果n = 99我们必须不计算99,因为语句是“找到n 以下所有 3 或 5 的倍数之和”。
    • 因此,如果 n 可被 整除,则不减去1最后一个不需要的数字也可以计算在内。3
  • **=>(3*x*(x+1)) / 2给出这些数字的总和

    • 如果n = 100总和 id3 + 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
    • 这里mfor1 to m是该序列的最后一个数字或总数或序列的长度,这就是我们找到可整除数字的计数的原因。
于 2019-10-25T06:03:48.503 回答