[ACCEPTED]-Fibonacci One-Liner-fibonacci
My favorite solution to this is to use a 3 Hash, the values of which can be determined 2 by an anonymous function:
fibonacci = Hash.new{ |h,k| h[k] = k < 2 ? k : h[k-1] + h[k-2] }
fibonacci[6] # => 8
fibonacci[50] # => 12586269025
It's a "genuine" one-liner 1 and very Ruby-ish.
Using a Ruby 1.9 Enumerator:
fib = Enumerator.new do |yielder|
i = 0
j = 1
loop do
i, j = j, i + j
yielder.yield i
end
end
p fib.take_while { |n| n <= 4E6 }
# => [1, 1, 2 ... 1346269, 2178309, 3524578]
As one line:
p Enumerator.new { |yielder| i, j = 0, 1; loop {i, j = j, i + j; yielder.yield i} }.take_while { |n| n <= 4E6}
0
Inspired on Alex's answer:
# Ruby 1.8.7
f = lambda { |x| x < 2 ? x : f.call(x-1) + f.call(x-2) }
puts f.call(6) #=> 8
# Ruby 1.9.2
f = ->(x){ x < 2 ? x : f[x-1] + f[x-2] }
puts f[6] #=> 8
0
My favorite is:
def fib(n)
(0..n).inject([1,0]) { |(a,b), _| [b, a+b] }[0]
end
from https://gist.github.com/1007228
0
How about this?
(((1 + 5 ** 0.5) / 2) ** 35 / 5 ** 0.5 - 0.5).to_i / 2
(See this answer for an explanation.)
0
Here's a ruby 2.0 solution, without using 13 inject/reduce which is not lazy:
(1..Float::INFINITY).
lazy.
with_object([0,1]).
map { |x, last| last[1] = last[0] + (last[0] = last[1]) }.
select { |x| x % 2 == 0 }.
take_while { |x| x < 4_000_000 }.
reduce(&:+)
I don't 12 particularly like the fibonacci generator, because 11 it doesn't include the initial 0. This solution 10 also takes advantage of the first odd number 9 being F3 (F1 in this sequence generator).
A 8 cleaner (Fibonacci-wise) and correct (In 7 Liber Abaci's definition) solution would 6 be:
(1..Float::INFINITY).
lazy.
with_object([0,1]).
map { |x, last| last[1] = last[0] + (last[0] = last[1]);last[0] }.
select { |x| x % 2 == 0 }.
take_while { |x| x < 4_000_000 }.
reduce(&:+)
This solution includes a semi-colon, but 5 I don't know if it counts when used this 4 way :).
[Update]
Here's a proper Fibonacci 3 generator (starting on 0) solution, with 2 no semi-colon (btw, is this a javascript 1 semi-colon wars thingy ?!?) :)
(1..Float::INFINITY).
lazy.
with_object([0,1]).
map { |x, last| last[0].tap { last[1] = last[0] + (last[0] = last[1]) } }.
select { |x| x % 2 == 0 }.
take_while { |x| x < 4_000_000 }.
reduce(&:+)
Building on Alex's Hash, this may make you 7 go blind, but it's one line, no semicolons 6 and eliminates the range dependency. the 5 instance_eval trick is very useful for oneliners 4 and golf, although it's horrible Ruby.
Hash.new{|h,k|h[k]=k<2?k:h[k-1]+h[k-2]}.update(sum: 0,1=>1).instance_eval {self[:sum]+= self[keys.last+1].even? ? self[keys.last] : 0 while values.last < 4E6 || puts(fetch :sum)}
Outputs: 4613732
I 3 warned you it was horrible. I can't make 2 it actually return the value without using 1 a semicolon, sorry.
I realize this is an ancient question and 18 has been classed as answered but no-one 17 manages to solve the question in one block, none 16 of them actually give the sum of the even 15 valued terms in one line and in one block 14 and with no semi colons (just noticed that 13 waynes does solve with one line but I thought 12 a one block solution might be nice in response 11 to aroth). here is a solution that does:
(1..Float::INFINITY).inject([0,1,0]){|a| if a[0]+a[1] < 4000000 then [a[1],a[0]+a[1],(a[0]+a[1]).even? ? a[2] + (a[0]+a[1]) : a[2]] else break a[2] end }
for 10 a slightly clearer version with one semi 9 colon.
(1..Float::INFINITY).inject([0,1,0]){|a| sum=a[0]+a[1]; if sum < 4000000 then [a[1],sum,sum.even? ? a[2] + sum : a[2]] else break a[2] end }
I figure I'll explain it too, three 8 pieces of information get carried forward 7 in the array (as a
at each iteration) the 6 first fibonacci number, the second fibonacci 5 number and the sum of the even terms. bearing 4 this in mind I think this code is quite 3 clear ruby.
it should be noted that this 2 is basically the same as clems except in 1 one block
puts (1..20).inject([0, 1]){|Fibonacci| Fibonacci << Fibonacci.last(2).inject(:+) }
This is the best solution I ever had used 13 to print the Fibonacci series using inject 12 keyword.
Explanation:
1) .inject([0,1])
will hold the 11 default value (0) first value of collection 10 (1) element of the series.
2) At first Fibonacci 9 object will have 0, 1 using Fibonacci.last(2)
that will be 8 passed through inject
3) .inject(:+)
will add the 0+1 7
4) This will add 0+1 = 1 and then will 6 be pushed to Fibonacci
which on next iteration with 5 outer inject([0,1])
will become inject(1,2)
here 1 is the value 4 after sum (0+1) and 2 is the next iteration 3 value of collection.
and so on till the 2 end of collection
So the series will be 1 like
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
Returns correct values up to Fib(70)
, beyond that 2 just an approximation. But extremely fast:
(((Math.sqrt(5.0) + 1.0) / 2.0)**n / Math.sqrt(5.0) + 0.5).floor
(see 1 https://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding for explanation)
I can think of 4 ways for now to achieve 10 the fibonacci goal!
- Using a stabby lambda:
puts 'Fibonacci Sequence in a Line: ', ->(a=1, b=0) { 10.times.collect { (a, b = b, a + b)[0] } }.call
This evaluates 10 series. But 9 if you want to get the user's number:
puts 'Fibonacci Sequence in a Line: ', ->(a=1, b=0) { gets.to_i.times.collect { (a, b = b, a + b)[0] } }.call
- Using the
tap
method:
[0, 1].tap { |a| 10.times { a.push(a[-1] + a[-2]) } }
- Using the
reduce / inject
method:
(1..10).reduce([0, 1]) { |a| a.push(a.last(2).sum) }
or
10.times.reduce([0, 1]) { |a| a.push(a.last(2).sum) }
- Using the
each_with_object
ormap.with_object
method:
10.times.each_with_object([0, 1]) { |_, a| a.push(a.last(2).sum) }
Note: If 8 you don't have Ruby 2.4+ you may not have 7 the sum method. In that case, you can add 6 the last two elements with ary[-2] + ary[-1]
or ary.last(2).reduce(:+)
.
Coming to 5 your problem:
By considering the terms in 4 the Fibonacci sequence whose values do not 3 exceed four million, find the sum of the 2 even-valued terms.
[0, 1].tap { |a| until (s = a.last(2).sum) > 4_000_000 do a.push(s) end }.select(&:even?).sum
Or (which is not that 1 great):
[0, 1].tap { |a| loop while a.push(a.last(2).sum)[-1] < 4_000_000 }.tap(&:pop).select(&:even?).sum
Outputs: 4613732
Hope this helps!
With the new lazy in ruby 2.0, you can write 1 like this.
puts (1..Float::INFINITY).lazy.map{|n| (0..n).inject([1,0]) {|(a,b), _| [b, a+b]}[0] }.take_while{|n| n < 4000000}.select{|x| x % 2 == 0}.reduce(:+)
As a summarizing solution for the answers 4 above, with my humble additions:
32.
times.
lazy.
with_object([0, 1]).map { |_, fib| fib[1] = fib[0] + fib[0] = fib[1]; fib[0] }.
take_while(&:>.to_proc.curry(2)[4*10**6]).
select(&:even?).
inject(:+)
I don't 3 really like how currying looks, but didn't 2 want it to look similar to other answers. Alternative 1 take_while
just for the case:
take_while { |value| value < 4*10**6 }.
Here's a one line ruby solution to Euler 1 prob #2
(0..4000000).take_while{|i| (0..i).reduce([1,0]){|(a,b), _| [b, a+b]}[0] <= 4000000 }.map{|i| (0..i).reduce([1,0]){|(a,b), _| [b, a+b]}[0] }.select{|i| i%2 == 0}.reduce(:+)
Or for better readability??
(0..4000000) .
take_while {|i| (0..i).reduce([1,0]){|(a,b), _| [b, a+b]}[0] <= 4000000} .
map {|i| (0..i).reduce([1,0]){|(a,b), _| [b, a+b]}[0]} .
select {|i| i%2 == 0} .
reduce(:+)
(1..32).inject([0, 1]) { |fib| fib << fib.last(2).inject(:+) }
0
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.