【问题标题】:Project Euler #1 - Lasso欧拉计划 #1 - 套索
【发布时间】:2013-09-16 13:12:55
【问题描述】:

作为学习如何在 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);

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

【问题讨论】:

  • 我会在 Lasso 9 中做很多不同的事情,所以我需要检查我自己的答案...这个 Chris 是什么问题?

标签: optimization lasso-lang


【解决方案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 中完全是多余的 :)

【讨论】:

    【解决方案2】:

    有一个有趣的故事,讲述了高斯曾经如何对数字求和,其中涉及一种有助于避免循环的策略。

    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 为后续运行做了一些聪明的事情,或者只是运气不好。

    【讨论】:

    • 非常有趣、准确,而且速度肯定要快得多!但是,它牺牲了很多可读性。
    【解决方案3】:

    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 sum id 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 for 1 to m 是该序列的最后一个数字或总数 或序列的长度,这就是我们找到可整除数的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多