Fibonacci One-Liner - ruby

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!

My favorite solution to this is to use a Hash, the values of which can be determined 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 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}

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

My favorite is:
def fib(n)
(0..n).inject([1,0]) { |(a,b), _| [b, a+b] }[0]
end
from https://gist.github.com/1007228

How about this?
(((1 + 5 ** 0.5) / 2) ** 35 / 5 ** 0.5 - 0.5).to_i / 2
(See this answer for an explanation.)

Here's a ruby 2.0 solution, without using 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 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:
(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 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 ?!?) :)
(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 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.
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 warned you it was horrible. I can't make it actually return the value without using a semicolon, sorry.

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:
(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 a slightly clearer version with one semi 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 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

puts (1..20).inject([0, 1]){|Fibonacci| Fibonacci << Fibonacci.last(2).inject(:+) }
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 inject
3) .inject(:+) will add the 0+1
4) This will add 0+1 = 1 and then will be pushed to Fibonacci which on next iteration with outer inject([0,1]) will become inject(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
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946

I can think of 4 ways for now to achieve 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 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 or map.with_object method:
10.times.each_with_object([0, 1]) { |_, a| a.push(a.last(2).sum) }
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] or ary.last(2).reduce(:+).
Coming to your problem:
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the 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 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!

Returns correct values up to Fib(70), beyond that just an approximation. But extremely fast:
(((Math.sqrt(5.0) + 1.0) / 2.0)**n / Math.sqrt(5.0) + 0.5).floor
(see https://en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding for explanation)

With the new lazy in ruby 2.0, you can write 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 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 really like how currying looks, but didn't want it to look similar to other answers. Alternative take_while just for the case:
take_while { |value| value < 4*10**6 }.

Here's a one line ruby solution to Euler 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(:+) }

Here is my one liner, with the #fib table being populated as we get the method returns..
#fib=[0,1];def fib num; return 0 if num < 0; #fib[num]||=fib(num-1)+fib(num-2);end

Simple and elegant is the best way, right?
a0 = 1; a1 = 1; 20.times {|i| b = a0 + a1; a0 = a1; a1 = b; puts b };
Output:
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
=> 20

Related

Using Ruby's array.bsearch_index(), is there an elegant way to look for the closest index in array so that array[i] is less than a number n?

I had to use something like
arr = [10, 20, 50, 80, 110]
(arr.bsearch_index{|a| a >= 50} || arr.length) - 1 # => 1
(arr.bsearch_index{|a| a >= 2000} || arr.length) - 1 # => 4
with the return value -1 meaning there is no such index. What if the numbers could be float, so you cannot look for 49 instead when n is 50. The code right now is a little bit messy. Is there a more elegant way to do it?
(Maybe it is just how bsearch_index() does it: to return nil when not found... so we just have to use bsearch(){ } || arr.length to convert it back to strictly numbers -- so that's just the way it is. bsearch_index has to either return only numbers or it can return nil as a design decision and it chose to return nil. But I am not sure if we just have to use the code above. Maybe the find-any mode of bsearch_index or some kind of way can do it and is more elegant.)
P.S. it might be interesting to use a reverse() operation or negating every element or something, but since those are O(n), it defeats the purpose of using a O(lg n) solution using binary search and we can just do a linear search.
In order to express "less than" directly (i.e. via <), you have to reverse the array:
rindex = arr.reverse.bsearch_index { |a| a < 50 }
#=> 4
To un-reverse the index:
arr.size - rindex - 1
#=> 1
In one line:
arr.reverse.bsearch_index { |a| a < 50 }.yield_self { |i| arr.size - i - 1 if i }
The the modifier-if handles i being nil, e.g. a < 10
Or simply use a descending array in the first place:
arr = [110, 80, 50, 20, 10]
arr.bsearch_index { |a| a < 50 } #=> 3
arr.bsearch_index { |a| a < 2000 } #=> 0
Not completely clear, but for a sorted Array I guess:
arr.bsearch_index{ |a| a >= n }.then { |i| i ? i - 1 : -1}
Or, since nil.to_i #=> 0
arr.bsearch_index{ |a| a >= n }.to_i - 1
# n = 49 #=> 1
# n = 50 #=> 1
# n = 51 #=> 2
# n = 111 #=> -1

Ruby loops style/convention

I'm wondering how I would create the following psuedo-esque code's conventional equivalent in Ruby. I've read quite a bit regarding standard practices but I'm just curious what the generally accepted/cleanest approach to this specific loop structure might be. I haven't come across a direct example.
for(i = 0, j = 10; i < 10 && j > 0; i++, j--){
//do something
}
Side note:
The intended purpose for this loop structure is to iterate through an array of arrays diagonally, the loop will contain a number of break-ing conditions.
The intended purpose for this loop structure is to iterate through an array of arrays diagonally.
Given a square array of arrays:
array = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
You can traverse it diagonally (from top right to bottom left) via:
array.each.with_index(1) do |row, i|
puts row[-i]
end
Output:
3
5
7
Or, if you prefer (or need) an index-based approach:
0.upto(2).zip(2.downto(0)).each do |i, j|
p i: i, j: j, element: array[i][j]
end
Output:
{:i=>0, :j=>2, :element=>3}
{:i=>1, :j=>1, :element=>5}
{:i=>2, :j=>0, :element=>7}
You could also use array.each_index.zip(array.each_index.reverse_each)
You can do this
(0..10).each do |j|
i = 10 - j
...
end
# 0, 10 -> 10, 0
Not an exact equivalent, but the result is the same:
10.times do |i|
j = 10 - i
# do something
end
Or
10.times.lazy.map{|i| [i, 10 - i]}.each do |i, j|
# do something
end
Either way you have a cleaner solution than #gates' because they don't leak i and j out of the block.
Or you can try a more functional approach just for fun :)
(λ = ->(i, j) {
# do something
λ.(i + 1, j - 1) if i < 9 and j > 1
}).(0, 10)
But don't do this on large matrices, because Ruby doesn't optimize tail recursion thus may lead to stack overflow.
Try this
i = 0
j = 10
loop do
break if i > 9 || j < 1
# do something
i = i + 1
j = j - 1
end

Project Euler Task 17. Find number of all letters from a range of numbers

The problem:
If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?
My solution:
require 'humanize'
arr, total = [], 0
(1..1000).to_a.map(&:humanize).each {|x| arr << x.delete(" ").delete("-")}.map {|y| total += y.length }
p total
Other solution privided, by #Arif in other question, gives the right answer (according to Project Euler):
p (1..1000).to_a.map(&:humanize).join.tr(" -", "").size
Why my solution is wrong? From my knowledge, these two implementations should give the same output...
Edit:
Found one more strange thing.
If I change 1000 to any number up to 20 and implementations looks like this:
(1..20).to_a.map(&:humanize).each {|x| arr << x.delete(" ").delete("-")}.map {|y| total += y.length }
p (1..20).to_a.map(&:humanize).join.tr(" -", "").size
I receive the same answer.....? What?
Your problem is that you are messing map with each.
(1..1000).to_a.map(&:humanize)
.each {|x| arr << x.delete(" ").delete("-") } # ??? each
.map {|y| total += y.length } # ??? map
The call to Enumerable#each returns the original Enumerable, not arr or whatever you’ve expected. Yes, you fulfilled arr, but the latter map is called on the original array, having all these spaces and dashes.
The correct way to implement it your way:
(1..1000).to_a.map(&:humanize)
.map { |x| x.delete(" ").delete("-") } # sic!, no need for arr
.each { |y| total += y.length } # no need to map here
Or, more ruby idiomatic:
(1..1000).to_a.map(&:humanize)
.map { |x| x.delete(" ").delete("-") }
.reduce(:+) # reduce by summing everything up
Or, even better (to_a is redundant here):
(1..1000).map(&:humanize)
.reduce(0) { |memo, x| memo + x.delete(" ").delete("-").length }

I ran into issue here with splitting array and adding it up

i am trying to find if array has 2 digits number and if i find one i want to add the two digit and make it single. then add all the numbers in array to come up with a a sum. here is my code so far. and also i am a noob and learning
class Imei
attr_accessor :Imei, :split_total1, :split_total2
def initialize(imei)
#imei = imei.to_i
#split_total1 = []
#split_total2 = []
end
def check_two_digit(num)
if num.to_s.length == 2
num = num.to_s.split(//).partition.with_index{|_,i| i.odd?}
num.each do |a, b|
a.to_i + b.to_i
end
else
num.to_i
end
end
def check_imei
if #imei.to_s.length == 15
split1, split2 = #imei.to_s.split(//).partition.with_index{|_, i| i.odd?}
split1.each do |a|
#split_total1 << check_two_digit(a.to_i * 2)
end
split2.pop
split2.each do |a|
#split_total2 << a.to_i
end
else
puts "IMEI NUMBER INVALID"
end
end
end
imei = Imei.new(123456789102222)
imei.check_imei
puts imei.split_total1.inspect
puts imei.split_total2.inspect
Find below the Luhn Algorithm I wrote in ruby
def luhn_10_valid? imei
digits = imei.reverse.chars.map(&:to_i)
digits.each_with_index.inject(0) do |sum, (digit, i)|
digit *= 2 if i.odd?
digit -= 9 if digit > 9
sum += digit
end % 10 == 0
end
For Luhn algorithm I really like the divmod method, which simplifies things
array.reverse.each_slice(2).map { |x, y|
y ||= 0
[x, (y * 2).divmod(10)]
}.flatten.inject(:+) % 10 == 0
If a contains only non-negative integers, this is one Ruby-like way to compute the sum:
a.reduce(0) {|t,i| t + (((10..99).cover? i) ? i.divmod(10).reduce(:+) : i )}
Explanation:
If i => 46, (10..99).cover?(46) => true, 46.divmod(10) => [4,6], [4,6].reduce(:+) => 10. Recall that reduce is aka inject. [4,6]reduce(:+) has the same result as (but,technically, is not 'equivalent to'):
[4,6].reduce { |u,j| u+j }
The zero initial value is needed for the first reduce, as
a[46].reduce {|t,i| t+(((10..99).cover? i) ? i.divmod(10).reduce(:+):i)}
#=> 46
which is incorrect.
If a instead contains string representations of integers and/or the integers may be negative, let me know and I'll change my answer accordingly.

Iterate over an infinite sequence in Ruby

I am trying to solve Project Euler problem #12:
The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number
would be 1 + 2 + 3 + 4 + 5 + 6 + 7 =
28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five
divisors.
What is the value of the first triangle number to have over five
hundred divisors?
Here's the solution that I came up with using Ruby:
triangle_number = 1
(2..9_999_999_999_999_999).each do |i|
triangle_number += i
num_divisors = 2 # 1 and the number divide the number always so we don't iterate over the entire sequence
(2..( i/2 + 1 )).each do |j|
num_divisors += 1 if i % j == 0
end
if num_divisors == 500 then
puts i
break
end
end
I shouldn't be using an arbitrary huge number like 9_999_999_999_999_999. It would be better if we had a Math.INFINITY sequence like some functional languages. How can I generate a lazy infinite sequence in Ruby?
Several answers are close but I don't actually see anyone using infinite ranges. Ruby supports them just fine.
Inf = Float::INFINITY # Ruby 1.9
Inf = 1.0/0 # Ruby before 1.9
(1..Inf).include?(2305843009213693951)
# => true
(1..Inf).step(7).take(3).inject(&:+)
# => 24.0
In your case
(2..Inf).find {|i| ((2..( i/2 + 1 )).select{|j| i % j == 0}.count+2)==42 }
=> 2880
Your brute force method is crude and can, potentially, take a very long time to finish.
In Ruby >= 1.9, you can create an Enumerator object that yields whatever sequence you like. Here's one that yields an infinite sequence of integers:
#!/usr/bin/ruby1.9
sequence = Enumerator.new do |yielder|
number = 0
loop do
number += 1
yielder.yield number
end
end
5.times do
puts sequence.next
end
# => 1
# => 2
# => 3
# => 4
# => 5
Or:
sequence.each do |i|
puts i
break if i >= 5
end
Or:
sequence.take(5).each { |i| puts i }
Programming Ruby 1.9 (aka "The Pickaxe Book"), 3rd. ed., p. 83, has an example of an Enumerator for triangular numbers. It should be easy to modify the Enumerator above to generate triangular numbers. I'd do it here, but that would reproduce the example verbatim, probably more than "fair use" allows.
Infinity is defined on Float (Ruby 1.9)
a = Float::INFINITY
puts a #=> Infinity
b = -a
puts a*b #=> -Infinity, just toying
1.upto(a) {|x| break if x >10; puts x}
Currrent versions of Ruby support generators heavily:
sequence = 1.step
In Ruby 2.6 this becomes much easier:
(1..).each {|n| ... }
Source: https://bugs.ruby-lang.org/issues/12912
This would be best as a simple loop.
triangle_number = 1
i = 1
while num_divisors < 500
i += 1
triangle_number += i
# ...
end
puts i
As Amadan mentioned you can use closures:
triangle = lambda { t = 0; n = 1; lambda{ t += n; n += 1; t } }[]
10.times { puts triangle[] }
Don't really think it is much slower than a loop. You can save state in class object too, but you will need more typing:
class Tri
def initialize
#t = 0
#n = 1
end
def next
#t += n
#n += 1
#t
end
end
t = Tri.new
10.times{ puts t.next }
Added:
For those who like longjmps:
require "generator"
tri =
Generator.new do |g|
t, n = 0, 1
loop do
t += n
n += 1
g.yield t
end
end
puts (0..19).map{ tri.next }.inspect
Building on Wayne's excellent answer and in the Ruby spirit of doing things with the least number of characters here is a slightly updated version:
sequence = Enumerator.new { |yielder| 1.step { |num| yielder.yield num } }
Obviously, doesn't solve the original Euler problem but is good for generating an infinite sequence of integers. Definitely works for Ruby > 2.0. Enjoy!
On Christmas Day 2018, Ruby introduced the endless range, providing a simple new approach to this problem.
This is implemented by ommitting the final character from the range, for example:
(1..)
(1...)
(10..)
(Time.now..)
Or to update using Jonas Elfström's solution:
(2..).find { |i| ((2..( i / 2 + 1 )).select { |j| i % j == 0 }.count + 2) == 42 }
Hope this proves useful to someone!
I believe that fibers (added in Ruby 1.9 I believe) may be close to what you want. See here for some information or just search for Ruby Fibers

Resources