Measure the distance between two strings with Ruby? - ruby

Can I measure the distance between two strings with Ruby?
I.e.:
compare('Test', 'est') # Returns 1
compare('Test', 'Tes') # Returns 1
compare('Test', 'Tast') # Returns 1
compare('Test', 'Taste') # Returns 2
compare('Test', 'tazT') # Returns 5

Much easier and fast due to native C binding:
gem install levenshtein-ffi
gem install levenshtein
require 'levenshtein'
Levenshtein.normalized_distance string1, string2, threshold
http://rubygems.org/gems/levenshtein
http://rubydoc.info/gems/levenshtein/0.2.2/frames

I found this for you:
def levenshtein_distance(s, t)
m = s.length
n = t.length
return m if n == 0
return n if m == 0
d = Array.new(m+1) {Array.new(n+1)}
(0..m).each {|i| d[i][0] = i}
(0..n).each {|j| d[0][j] = j}
(1..n).each do |j|
(1..m).each do |i|
d[i][j] = if s[i-1] == t[j-1] # adjust index into string
d[i-1][j-1] # no operation required
else
[ d[i-1][j]+1, # deletion
d[i][j-1]+1, # insertion
d[i-1][j-1]+1, # substitution
].min
end
end
end
d[m][n]
end
[ ['fire','water'], ['amazing','horse'], ["bamerindos", "giromba"] ].each do |s,t|
puts "levenshtein_distance('#{s}', '#{t}') = #{levenshtein_distance(s, t)}"
end
That's awesome output: =)
levenshtein_distance('fire', 'water') = 4
levenshtein_distance('amazing', 'horse') = 7
levenshtein_distance('bamerindos', 'giromba') = 9
Source: http://rosettacode.org/wiki/Levenshtein_distance#Ruby

There is an utility method in Rubygems that actually should be public but it's not, anyway:
require "rubygems/text"
ld = Class.new.extend(Gem::Text).method(:levenshtein_distance)
p ld.call("asd", "sdf") => 2

Much simpler, I'm a Ruby show-off at times...
# Levenshtein distance, translated from wikipedia pseudocode by ross
def lev s, t
return t.size if s.empty?
return s.size if t.empty?
return [ (lev s.chop, t) + 1,
(lev s, t.chop) + 1,
(lev s.chop, t.chop) + (s[-1, 1] == t[-1, 1] ? 0 : 1)
].min
end

Ruby 2.3 and later ship with the did_you_mean gem which includes DidYouMean::Levenshtein.distance. Fit for most cases and available by default.
DidYouMean::Levenshtein.distance("Test", "est") # => 1

I made a damerau-levenshtein gem where algorithms are implemented in C
require "damerau-levenshtein"
dl = DamerauLevenshtein
dl.distance("Something", "Smoething") #returns 1

I like DigitalRoss' solution above. However, as pointed out by dawg, its runtime grows on the order O(3^n), which is no good for longer strings.
That solution can be sped up significantly using memoization, or 'dynamic programming':
def lev(string1, string2, memo={})
return memo[[string1, string2]] if memo[[string1, string2]]
return string2.size if string1.empty?
return string1.size if string2.empty?
min = [ lev(string1.chop, string2, memo) + 1,
lev(string1, string2.chop, memo) + 1,
lev(string1.chop, string2.chop, memo) + (string1[-1] == string2[-1] ? 0 : 1)
].min
memo[[string1, string2]] = min
min
end
We then have much better runtime, (I think it's almost linear? I'm not really sure).
[9] pry(main)> require 'benchmark'
=> true
[10] pry(main)> #memo = {}
=> {}
[11] pry(main)> Benchmark.realtime{puts lev("Hello darkness my old friend", "I've come to talk with you again")}
26
=> 0.007071999832987785

Related

Writing Ruby inject method?

Im a bit confused at why this answer is "wrong" based on Ruby's own interpretation of the "Inject" method (for an array in this case, Im doing the "Odin Projects" projects for learning tasks)
def my_inject(start = nil)
memo = self[0] if start.nil?
for i in 0...self.length do
puts "#{memo}:#{self[i]} Results=#{yield(memo,self[i])}"
memo = yield(memo,self[i])
end
return memo
end
[5,6,7,8,9,10].my_inject { |sum, n| sum + n }
The Above returns this specifically:
5:5 Results=10
10:6 Results=16
16:7 Results=23
23:8 Results=31
31:9 Results=40
40:10 Results=50
=> 50
Which makes sense right? When no starting value is defined, the first value is used. However according to Ruby's API docs:"Inject" it should be 45....
Which doesn't make sense to me. We start with a memo of the first value and add it to the "elements" value. Which is 10 (in this case)...and so forth. Or are they saying when you DO NOT specify a value? you should skip the first array value?
I mean if I add up 5+6+7+8+9+10 yeah that is correctly 45, but if im doing what the block wants me to do, I feel like "50" makes more sense? Although obviously im wrong, im just not sure where.
I mean sure I could start the index off at 1 if we are not given a starting value...but that just seems odd.
Thanks
As people have pointed out in comments, your solution double taps the first element if no argument is provided.
Here's an implementation that is pretty straightforward, drops some unnecessary elements your solution included, and works for more than just arrays:
module Enumerable
def my_inject(memo = nil)
each { |x| memo = memo.nil? ? x : yield(memo, x) }
memo
end
end
p (1..5).my_inject(&:*) # 5 factorial => 120
p (1..5).my_inject(2, &:*) # 5 factorial doubled => 240
p %w(3 4 5).my_inject(&:+) # string concatenation => "345"
p %w(3 4 5).my_inject("hello", &:+) # concatenation w/ prefix => "hello345"
p %w(3 4 5).my_inject("howdy") { |memo, x| memo + x } # prefix and block => "howdy345"
ADDENDUM
If you want to go further and handle Symbol or String arguments as Enumerable#inject does, you need to do some preprocessing to determine what you're dealing with:
module Enumerable
def my_inject(memo = nil, sym = nil, &block)
memo = memo.to_sym if memo.is_a?(String) && !sym && !block
block, memo = memo.to_proc, nil if memo.is_a?(Symbol) && !sym
sym = sym.to_sym if sym.is_a?(String)
block = sym.to_proc if sym.is_a?(Symbol)
# Ready to rock & roll
each { |x| memo = memo.nil? ? x : block.yield(memo, x) }
memo
end
end
# A variety of test cases
p (1..4).my_inject(:*) # 4 factorial via Symbol => 24
p (1..5).my_inject('*') # 5 factorial via String => 120
p (1..6).my_inject { |memo, x| memo * x } # 6 factorial via block => 720
p (1..5).my_inject(2, &:*) # 5 factorial doubled via Proc => 240
p (1..5).my_inject(3, :*) # 5 factorial tripled via Symbol => 360
p (1..5).my_inject(4, '*') # 5 factorial quadrupled via String => 480
p %w(3 4 5).my_inject(&:+) # string concatenation via Proc => "345"
p %w(3 4 5).my_inject("hello", &:+) # prefix and Proc => "hello345"
p %w(3 4 5).my_inject("howdy") { |memo, x| memo + x } # prefix and block => "howdy345"
p %w(3 4 5).my_inject("yowza", :+) # prefix and Symbol => "yowza345"
p %w(3 4 5).my_inject("yoiks", '+') # prefix and String => "yoiks345"

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.

Ruby #select, but only select a certain number

Whats the best way in Ruby to do something like my_array.select(n){ |elem| ... }, where the n means "I only want n elements returned, and stop evaluating after that number is reached"?
This should do the trick:
my_array.select(n) { |elem| elem.meets_condition? }.take(n)
However, this will still evaluate all items.
If you have a lazy enumerator, you could do this in a more efficient manner.
https://github.com/ruby/ruby/pull/100 shows an attempt at enabling this feature.
You can easily implement lazy_select:
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |e|
yielder.yield(e) if yield(e)
end
end
end
end
Then things like
(1..10000000000).to_enum.lazy_select{|e| e % 3 == 0}.take(3)
# => [3, 6, 9]
execute instantly.
Looks like there's no avoiding a traditional loop if you're using stock 1.8.7 or 1.9.2...
result = []
num_want = 4
i = 0
while (elem = my_array[i]) && my_array.length < num_want
result << elem if elem.some_condition
i += 1
end
You could make an Enumerable-like extension which has your desired selectn semantics:
module SelectN
def selectn(n)
out = []
each do |e|
break if n <= 0
if yield e
out << e
n -= 1
end
end
out
end
end
a = (0..9).to_a
a.select{ |e| e%3 == 0 } # [0, 3, 6, 9]
a.extend SelectN
a.selectn(1) { |e| e%3 == 0 } # [0]
a.selectn(3) { |e| e%3 == 0 } # [0, 3, 6]
# for convenience, you could inject this behavior into all Arrays
# the usual caveats about monkey-patching std library behavior applies
class Array; include SelectN; end
(0..9).to_a.selectn(2) { |e| e%3 == 0 } # [0,3]
(0..9).to_a.selectn(99) { |e| e%3 == 0 } # [0,3, 6, 9]
Why not flip this around and do the #take before the #select:
my_array.take(n).select { |elem| ... }
That will ensure you only do your computation for n number of items.
EDIT:
Enumerable::Lazy is known to be slower, but if your computation is known to be more computationally expensive than the lazy slowness, you can use the Ruby 2.0 feature:
my_array.lazy.select { |elem| ... }.take(n)
See: http://blog.railsware.com/2012/03/13/ruby-2-0-enumerablelazy/
I guess broken loop can be done in old-fashioned loop style with break or something like this:
n = 5
[1,2,3,4,5,6,7].take_while { |e| n -= 1; n >= 0 && e < 7 }
In functional language this would be recursion, but without TCO it doesn't make much sense in Ruby.
UPDATE
take_while was stupid idea as dbenhur pointed out, so I don't know anything better than a loop.

Fibonacci One-Liner

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

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