最近我在玩欧拉计划中的第14个问题:在范围1-1,000,000内,哪个数字生成的Collatz序列最长?
我知道必须使用备忘录技术以获得合理的时间,下面这段Python
代码使用该技术(将值存储到字典中)相对较快地返回了一个答案:
#!/usr/bin/env python
L = 1_000_000
cllens={1:1}
cltz = lambda n: 3*n + 1 if n%2 else n//2
def cllen(n):
if n not in cllens: cllens[n] = cllen(cltz(n)) + 1
return cllens[n]
maxn=1
for i in range(1,L+1):
ln=cllen(i)
if (ln > cllens[maxn]): maxn=i
print(maxn)
(改编自此处; 我更喜欢这个版本,它不使用
max
,因为我可能想要调整它以返回最长的10个序列等)。
我尽力保持语义上的接近,将其翻译成了Raku
:
#!/usr/bin/env perl6
use v6;
my $L=1_000_000;
my %cllens = (1 => 1);
sub cltz($n) { ($n %% 2) ?? ($n div 2) !! (3*$n+1) }
sub cllen($n) {
(! %cllens{$n}) && (%cllens{$n} = 1+cllen($n.&cltz));
%cllens{$n};
}
my $maxn=1;
for (1..$L) {
my $ln = cllen($_);
($ln > %cllens{$maxn}) && ($maxn = $_)
}
say $maxn
以下是我一直运行这些代码时得到的时间类型:
$ time <python script>
837799
real 0m1.244s
user 0m1.179s
sys 0m0.064s
另一方面,在 Raku
中:
$ time <raku script>
837799
real 0m21.828s
user 0m21.677s
sys 0m0.228s
问题
我是不是在两者之间翻译有误,或者差异是启动虚拟机等无法调和的问题?
是否有聪明的技巧/习语可以应用于Raku
代码,将其速度显著提高?
附言
当然,这并不是关于这个特定的Euler project
问题;我更广泛地感兴趣的是是否有适用于Raku
的任何神奇加速秘籍我不知道。
Inline
直接使用现有(或新的)外语代码(无需手动翻译),就可以像使用本地Raku一样使用外国特性!所有数据、异常等都会自动编组。如果您单击链接,您将看到正在开发的Inline::Python
。也许可以试试? - raiph