【发布时间】:2012-03-16 12:48:00
【问题描述】:
我已经开始将 project Euler site 视为学习 Haskell 并改进我的 Python 和 Ruby 的一种方式。我认为 Haskell 和 Python 版本还可以,但我确信 Ruby 必须有更清洁的方法。
这不是关于如何让一种语言看起来像另一种语言。
这是Problem 1:
问:将所有小于一千且是 3 或 5 倍数的自然数相加。
哈斯克尔:
sum [ x | x <- [1..999], mod x 3 == 0 || mod x 5 == 0 ]
Python:
sum ( [ x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0 ] )
鲁比:
(1..999) . map {|x| x if x % 3 == 0 || x % 5 == 0 } . compact . inject(:+)
他们都给出了相同的答案。
好的,所以 Python 可以变成:
sum ( x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0 )
它现在是一个生成器(这是一件好事,因为我们没有存储列表)
但更有趣的是:
sum( set(range(0,1000,3)) | set(range(0,1000,5)) )
出于某种原因,我再次查看此内容并尝试了一种应该是恒定时间的求和方法。在 Python 3 中:
def step_sum(mn,mx,step):
amax = mx - (mx - mn) % step
return (mn + amax) * ((1 + ((amax - mn) / step)) / 2)
step_sum(3,999,3) + step_sum(5,999,5) - step_sum(15,999,15)
Ruby 可以变成:
(1..999) . select {|x| x % 3 == 0 || x % 5 == 0} . inject(:+)
或
(1..999) . select {|x| x % 3 == 0 or x % 5 == 0} . reduce(:+)
我假设与map 不同,select 不会产生“nul”,因此无需调用compact。不错。
Haskell 也可以是:
let ƒ n = sum [0,n..999] in ƒ 3 + ƒ 5 - ƒ 15
或者说得更清楚:
let ƒ n = sum [ 0 , n .. 999 ] in ƒ 3 + ƒ 5 - ƒ (lcm 3 5)
作为一个让我们自己提供两个数字的函数:
ƒ :: (Integral a) => a -> a -> a
ƒ x y = let ƒ n = sum [0,n..999] in ƒ x + ƒ y - ƒ (lcm x y)
【问题讨论】:
-
Ruby 总是让我想起 Perl... 强大而紧凑的语法,但有时几周后您很难阅读自己的代码。
-
嗨,我不了解 ruby,这并不能回答您的问题,但是...恭喜您选择了 Project Euler,这太棒了...对于那个特定的问题,有一个恒定的时间解决方案问题,如果你想优化一点;)如果你不知道 Summation,检查一下,它会变得非常方便。
-
在 Python 中,您可以删除方括号。
-
@Jwosty 您的意思是代码还是您对这个问题持哲学态度?如果是代码......那么它应该提供问题'Q'的答案。
-
@eumiro:删除方括号会将列表理解转换为生成器,如果您不打算存储列表,这是一个非常好的主意(性能方面)。
标签: python ruby haskell list-comprehension