Pete Hodgson <> writes:
> Hi Folks,
>
> Given a sorted enumeration I need to find the first gap in a sequence.
>
> e.g.
> 3 == find_gap [1,2,4,5]
> nil == find_gap [1,2,3,4]
>
> Here's the best I can come up with
>
> def first_gap( seq )
> seq.each_cons(2) do |l,r|
> _next = l.next
> return _next if r!= _next
> end
> nil
> end
>
> but it seems rather ugly. Anyone have a more elegant implementation?
I think your version is pretty readable. However, it appears you do
pay a 60% speed penalty with the Enumerator version. So I guess it
depends on whether conciseness and readability are more important than
efficiency, or not.
--- snip ---
require 'enumerator'
require 'benchmark'
include Benchmark
def first_gap list
list.each_cons(2) do |l,r|
_next = l.next
return _next unless r == _next
end
nil
end
def other_gap list
prev = nil
list.each do |e|
if prev && (n = prev.next) != e
return n
end
prev = e
end
nil
end
t = (1..100).to_a
[100, 250, 500].each do |n|
t = (1..n).to_a
bm(5) do |x|
x.report('first') { 1_000.times { first_gap(t) } }
x.report('other') { 1_000.times { other_gap(t) } }
end
end
--- snip ---
~/temp$ ruby first_gap.rb
user system total real
first 0.700000 0.250000 0.950000 ( 0.957255)
other 0.430000 0.170000 0.600000 ( 0.604145)
user system total real
first 1.720000 0.630000 2.350000 ( 2.354915)
other 1.070000 0.420000 1.490000 ( 1.490321)
user system total real
first 3.470000 1.250000 4.720000 ( 4.838116)
other 2.120000 0.840000 2.960000 ( 3.018840)
--
Brian Adkins
http://www.lojic.com/
http://lojic.com/blog/