Largest correct index
Here's an adapted version of @AndrewGrimm's excellent answer :
a = ("a".."z").to_a
start = Time.now
largest_correct_index = 1
smallest_incorrect_index = nil
until smallest_incorrect_index == largest_correct_index + 1
if smallest_incorrect_index.nil?
next_number_to_try = largest_correct_index * 1000
else
next_number_to_try = (smallest_incorrect_index + largest_correct_index) / 2 # Geometric mean would be more efficient, but more risky
end
if next_number_to_try <= largest_correct_index ||
smallest_incorrect_index && next_number_to_try >= smallest_incorrect_index
raise "Can't happen case"
end
begin
a[next_number_to_try]
largest_correct_index = next_number_to_try
rescue RangeError
smallest_incorrect_index = next_number_to_try
end
end
finish = Time.now
puts "The largest correct index is #{largest_correct_index}"
puts "The smallest incorrect index is #{smallest_incorrect_index}"
puts "Calculation took #{finish - start} seconds"
On 32-bit Ruby, it returned 2**31-1
:
The largest correct index is 2147483647
The smallest incorrect index is 2147483648
Calculation took 0.0 seconds
On 64-bit Ruby and JRuby, it returned 2**63-1
:
The largest correct index is 9223372036854775807
The smallest incorrect index is 9223372036854775808
Calculation took 0.000250378 seconds
So it looks like @akuhn's answer should be good enough in most cases.
Alternative
Depending on your needs, you could also use a hash :
a = ('a'..'z').to_a
# ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
h = ('a'..'z').map.with_index { |l, i| [i, l] }.to_h
# {0=>"a", 1=>"b", 2=>"c", 3=>"d", 4=>"e", 5=>"f", 6=>"g", 7=>"h", 8=>"i", 9=>"j", 10=>"k", 11=>"l", 12=>"m", 13=>"n", 14=>"o", 15=>"p", 16=>"q", 17=>"r", 18=>"s", 19=>"t", 20=>"u", 21=>"v", 22=>"w", 23=>"x", 24=>"y", 25=>"z"}
require 'fruity'
compare do
_array { a[rand(26)] }
_hash { h[rand(26)] }
end
It doesn't seem to impact performances negatively :
Running each test 16384 times. Test will take about 1 second.
_array is similar to _hash
All those :
h[-1]
h[:default]
h[Float::INFINITY]
h[2**1024-1]
would return nil
.