斐波那契单线
我正在尝试用 Ruby 单行代码解决 Project Euler 中的问题,我很好奇是否还有更多问题二的优雅解决方案:
斐波那契数列中的每一项新项都是通过添加前两项而生成的。从 1 和 2 开始,前 10 项将是:
1、2、3、5、8、13、21、34、55、89、...
考虑斐波那契数列中值不超过四百万的项,求偶数项的总和。
这是我在 Ruby 中的一行解决方案:
(1..32).inject([0,1]) {|arr, i| (arr << arr[-1] + arr[-2] if arr[-1] + arr[-2] <= 4000000) || arr}.inject(0) {|total, i| total += i.even? ? i : 0}
我在这里主要关心的是我使用范围 (1..32) 只是因为我碰巧知道这就是斐波那契数列中的数字开始超过 4,000,000 之前所必需的全部内容。我希望以某种方式将其内置到单行中,但我一直无法弄清楚。
不允许使用分号!
I'm trying to solve questions from Project Euler in Ruby one-liners, and I'm curious if there's a more elegant solution for question two:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
Here is my one line solution in Ruby:
(1..32).inject([0,1]) {|arr, i| (arr << arr[-1] + arr[-2] if arr[-1] + arr[-2] <= 4000000) || arr}.inject(0) {|total, i| total += i.even? ? i : 0}
My main concern here is that I'm using the range (1..32) only because I happen to know that that's all that's necessary until numbers in the Fibonacci sequence begin to exceed 4,000,000. I would prefer that this be built into the one-line somehow, but I haven't been able to figure it out.
Semi-colons are not allowed!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
我最喜欢的解决方案是使用 Hash,它的值可以由匿名函数确定:
它是一个“真正的”单行代码并且非常 Ruby 风格。
My favorite solution to this is to use a Hash, the values of which can be determined by an anonymous function:
It's a "genuine" one-liner and very Ruby-ish.
使用 Ruby 1.9 枚举器:
作为一行:
Using a Ruby 1.9 Enumerator:
As one line:
受到亚历克斯的回答的启发:
Inspired on Alex's answer:
我最喜欢的是:
来自 https://gist.github.com/1007228
My favorite is:
from https://gist.github.com/1007228
这个怎么样?
(参见这个答案 进行解释。)
How about this?
(See this answer for an explanation.)
这是一个 ruby 2.0 解决方案,不使用注入/减少,这并不懒惰:
我不是特别喜欢斐波那契生成器,因为它不包括初始 0。该解决方案还利用了第一个奇数 F3(在此序列生成器中为 F1)。
一个更干净(斐波那契)和正确(在 Liber Abaci 的定义中)的解决方案是:
该解决方案包含一个分号,但我不知道以这种方式使用它是否有效:)。
[更新]
这是一个正确的斐波那契生成器(从 0 开始)解决方案,没有分号(顺便说一句,这是 javascript 分号战争吗?!?):)
Here's a ruby 2.0 solution, without using inject/reduce which is not lazy:
I don't particularly like the fibonacci generator, because it doesn't include the initial 0. This solution also takes advantage of the first odd number being F3 (F1 in this sequence generator).
A cleaner (Fibonacci-wise) and correct (In Liber Abaci's definition) solution would be:
This solution includes a semi-colon, but I don't know if it counts when used this way :).
[Update]
Here's a proper Fibonacci generator (starting on 0) solution, with no semi-colon (btw, is this a javascript semi-colon wars thingy ?!?) :)
建立在 Alex 的哈希之上,这可能会让你失明,但它只有一行,没有分号,并且消除了范围依赖性。 instance_eval 技巧对于单线和高尔夫非常有用,尽管它是可怕的 Ruby。
输出:4613732
我警告过你这太可怕了。抱歉,我无法让它在不使用分号的情况下实际返回值。
Building on Alex's Hash, this may make you go blind, but it's one line, no semicolons and eliminates the range dependency. the instance_eval trick is very useful for oneliners and golf, although it's horrible Ruby.
Outputs: 4613732
I warned you it was horrible. I can't make it actually return the value without using a semicolon, sorry.
我意识到这是一个古老的问题,已被归类为已回答,但没有人能够在一个块中解决这个问题,他们中没有一个人真正给出一行和一个块中偶数项的总和,并且没有分号(刚刚注意到韦恩斯确实用一行解决了问题,但我认为一个块解决方案可能会很好地响应阿罗斯)。这是一个解决方案:
带有一个分号的稍微清晰的版本。
我想我也会解释一下,数组中会传递三条信息(在每次迭代时作为
a
):第一个斐波那契数、第二个斐波那契数以及偶数项的总和。考虑到这一点,我认为这段代码是相当清晰的 ruby。应该注意的是,除了一个块之外,这与 clems 基本相同
I realize this is an ancient question and has been classed as answered but no-one manages to solve the question in one block, none of them actually give the sum of the even valued terms in one line and in one block and with no semi colons (just noticed that waynes does solve with one line but I thought a one block solution might be nice in response to aroth). here is a solution that does:
for a slightly clearer version with one semi colon.
I figure I'll explain it too, three pieces of information get carried forward in the array (as
a
at each iteration) the first fibonacci number, the second fibonacci number and the sum of the even terms. bearing this in mind I think this code is quite clear ruby.it should be noted that this is basically the same as clems except in one block
这是我曾经使用过的使用注入关键字打印斐波那契数列的最佳解决方案。
解释:
1)
.inject([0,1])
将保存系列的集合 (1) 元素的默认值 (0) 第一个值。2) 首先斐波那契对象将有 0, 1 使用
Fibonacci.last(2)
将通过注入传递3)
.inject(:+)
将添加 0+14) 这将添加 0+1 = 1,然后将被推送到
Fibonacci
,在下一次迭代时外部inject([0,1])
将变为注入(1,2)
这里1是sum(0+1)之后的值,2是collection的下一次迭代值。
依此类推,直到收集结束
所以该系列将是这样的
This is the best solution I ever had used to print the Fibonacci series using inject keyword.
Explanation:
1)
.inject([0,1])
will hold the default value (0) first value of collection (1) element of the series.2) At first Fibonacci object will have 0, 1 using
Fibonacci.last(2)
that will be passed through inject3)
.inject(:+)
will add the 0+14) This will add 0+1 = 1 and then will be pushed to
Fibonacci
which on next iteration with outerinject([0,1])
will becomeinject(1,2)
here 1 is the value after sum (0+1) and 2 is the next iteration value of collection.
and so on till the end of collection
So the series will be like
我现在能想到4种方法来实现斐波那契目标!
这会评估 10 系列。但如果你想获取用户的号码:
tap
方法:reduce/inject
方法:或
each_with_object
或map.with_object
方法:注意:如果您没有 Ruby 2.4+,则可能没有 sum 方法。在这种情况下,您可以使用
ary[-2] + ary[-1]
或ary.last(2).reduce(:+)
添加最后两个元素。来到你的问题:
或者(这不是那么好):
输出:
4613732
希望这有帮助!
I can think of 4 ways for now to achieve the fibonacci goal!
This evaluates 10 series. But if you want to get the user's number:
tap
method:reduce / inject
method:or
each_with_object
ormap.with_object
method:Note: If you don't have Ruby 2.4+ you may not have the sum method. In that case, you can add the last two elements with
ary[-2] + ary[-1]
orary.last(2).reduce(:+)
.Coming to your problem:
Or (which is not that great):
Outputs:
4613732
Hope this helps!
返回
Fib(70)
以内的正确值,除此之外只是近似值。但速度非常快:(参见https://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding 用于解释)
Returns correct values up to
Fib(70)
, beyond that just an approximation. But extremely fast:(see https://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding for explanation)
使用ruby 2.0中新的lazy,你可以这样写。
With the new lazy in ruby 2.0, you can write like this.
作为上述答案的总结解决方案,我做了一些谦虚的补充:
我不太喜欢柯里化的外观,但不希望它看起来与其他答案相似。针对这种情况的替代
take_while
:As a summarizing solution for the answers above, with my humble additions:
I don't really like how currying looks, but didn't want it to look similar to other answers. Alternative
take_while
just for the case:这是 Euler 问题 #2 的单行 ruby 解决方案
或者为了更好的可读性?
Here's a one line ruby solution to Euler prob #2
Or for better readability??
(1..32).inject([0, 1]) { |fib|纤维 << fib.last(2).inject(:+) }
(1..32).inject([0, 1]) { |fib| fib << fib.last(2).inject(:+) }
这是我的一个行,当我们得到方法返回时,
@fib
表被填充。Here is my one liner, with the
@fib
table being populated as we get the method returns..简单又优雅才是最好的方式吧?
输出:
Simple and elegant is the best way, right?
Output: