【发布时间】:2023-04-07 06:03:01
【问题描述】:
我最近在玩problem 14 中的Euler project
:1..1_000_000
范围内的哪个数字产生最长的Collatz sequence?
我知道必须memoize 才能获得合理时间的问题,下面的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)
(改编自here;我更喜欢这个不使用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
问题
我是不是在两者之间翻译错误,或者差异是启动 VM 等不可调和的问题?
我可以对Raku
代码应用一些巧妙的调整/习语来大大加快它的速度吗?
一边
当然,这与这个特定的Euler project
问题无关;我更感兴趣的是是否有任何适合Raku
的神奇加速奥术我不知道。
【问题讨论】:
-
也许获得 Raku “神奇加速”的 最佳 方法是将其翻译成 Python :-) 抱歉,无法抗拒,我已经很久没有使用 Perl,我可能无法提供 有用的 答案,除了可能在您的代码中插入时间陷阱以查看延迟在哪里。
-
:-) 很公平,但这并没有减损我对这里实际发生的事情的内在兴趣。
-
grobber,同意,我不是说你的问题无效,实际上很好。
-
@paxdiablo, .@grobber “也许最好的 方法来获得 Raku “神奇的加速”是将它翻译成 Python ...我可能无法提供有用答案”。 :-) 你有! :) Raku(do) 支持卓越的自动翻译系统。通过
Inline
只需直接 使用现有的(或新的)外语代码(无需手动 翻译)。使用外来功能,就好像它们是 Raku 的原生功能一样!所有数据、异常等都会自动编组。如果您单击该链接,您将看到正在开发的Inline::Python
。试试看? -
可能会看到使用“使用实验性:缓存”功能的改进。
标签:
python
raku
memoization
collatz
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:为什么这个记忆化的 Euler14 实现在 Raku 中比 Python 慢得多? - Python技术站