diff --git a/searches/interpolation_search.rb b/searches/interpolation_search.rb new file mode 100644 index 00000000..4fe37894 --- /dev/null +++ b/searches/interpolation_search.rb @@ -0,0 +1,39 @@ +# Performs interpolation search on a sorted numeric array. +# Returns the index of the target element or -1 when target is absent. +# Raises ArgumentError if the input array is not sorted in ascending order. +def interpolation_search(array, target) + raise ArgumentError, 'Input must be an array' unless array.is_a?(Array) + return -1 if array.empty? + + unless array.each_cons(2).all? { |left, right| left <= right } + raise ArgumentError, 'Array must be sorted in ascending order' + end + + left = 0 + right = array.length - 1 + + while left <= right && target >= array[left] && target <= array[right] + return left if array[left] == target + return right if array[right] == target + + value_range = array[right] - array[left] + if value_range.zero? + return array[left] == target ? left : -1 + end + + position = left + ((target - array[left]) * (right - left) / value_range) + return -1 if position < left || position > right + + current = array[position] + + if current == target + return position + elsif current < target + left = position + 1 + else + right = position - 1 + end + end + + -1 +end diff --git a/searches/interpolation_search_test.rb b/searches/interpolation_search_test.rb new file mode 100644 index 00000000..67203516 --- /dev/null +++ b/searches/interpolation_search_test.rb @@ -0,0 +1,31 @@ +require 'minitest/autorun' +require_relative './interpolation_search' + +class TestInterpolationSearch < Minitest::Test + def test_finds_existing_element + array = [2, 4, 6, 8, 10, 12, 14] + assert_equal 3, interpolation_search(array, 8) + end + + def test_returns_negative_one_for_missing_element + array = [10, 20, 30, 40, 50] + assert_equal(-1, interpolation_search(array, 35)) + end + + def test_handles_empty_array + assert_equal(-1, interpolation_search([], 7)) + end + + def test_handles_uniform_values + array = [5, 5, 5, 5] + assert_equal 0, interpolation_search(array, 5) + assert_equal(-1, interpolation_search(array, 4)) + end + + def test_raises_when_array_not_sorted + array = [3, 1, 2] + assert_raises ArgumentError do + interpolation_search(array, 1) + end + end +end