KitchenSink v1.3.9 KitchenSink.Algorithms View Source
This is a collection of algorithms.
The binary search fit
function
The search is controlled by the fit
function which is passed the value to
test and returns :ok
if the value is good enough, :high
if the next
value to test should be higher, or :low
if the next value should be
lower.
Link to this section Summary
Functions
binary_search
performs a binary search over a range.
Link to this section Types
binary_interval_search_fit_func()
View Sourcebinary_interval_search_fit_func() :: (binary_interval_search_position(), any() -> :ok | :high | :low)
binary_interval_search_position()
View Sourcebinary_interval_search_position() :: number()
binary_interval_search_result()
View Sourcebinary_interval_search_result() :: {:ok, binary_interval_search_position()} | :not_found
binary_search_fit_func()
View Sourcebinary_search_fit_func() :: (binary_search_position(), any() -> :ok | :high | :low)
binary_search_result()
View Sourcebinary_search_result() :: {:ok, binary_search_position()} | :not_found
binary_search_strategy()
View Sourcebinary_search_strategy() :: :midpoint | :interval
Link to this section Functions
binary_search(start, finish, fit, target, strategy \\ :midpoint)
View Sourcebinary_search( binary_search_position(), binary_search_position(), binary_search_fit_func(), any(), binary_search_strategy() ) :: binary_search_result()
hybrid_binary_search(range_list, fit, target, strategy \\ :midpoint)
View Sourcebinary_search
performs a binary search over a range.
The binary search function requires a midpoint strategy to be specified. If no strategy
is specified, it defaults to :midpoint
Examples using the :midpoint
strategy
iex> names = ~w(Adrian Bill Robert Tony) # Sorted!
iex> search_names = fn(position, target) ->
...> current = Enum.at(names, position)
...> cond do
...> current < target -> :high
...> current == target -> :ok
...> current > target -> :low
...> end
...> end
iex>
iex> Algorithms.binary_search(0, 3, search_names, "Tony", :midpoint)
{:ok, 3}
iex> Algorithms.binary_search(0, 3, search_names, "Phil", :midpoint)
{:not_found, 2}
It is possible to override the calculation of the midpoint for the binary search, and that is "...left as an exercise for the reader."
It is also possible to binary-search multiple ranges at the same time, in case you are trying to find some balance between of a number of variable factors.
Example (albeit a contrived one) of searching multiple ranges simultaneously
iex> solve = fn (pos, desired_result) -> ...> result = Enum.reduce(pos, fn (x, acc) -> x + acc end) ...> cond do ...> result < desired_result -> :high ...> result == desired_result -> :ok ...> result > desired_result -> :low ...> end ...> end iex> Algorithms.hybrid_binary_search([2..40, 20..100], solve, 27, :midpoint)
Examples using the :interval
strategy
To see where y = 10 + x³ and y = 1000 + x² intersect
iex> solve = fn(position, _) ->
...> y1 = 10 + :math.pow(position, 3)
...> y2 = 1000 + :math.pow(position, 2)
...> difference = y1 - y2
...>
...> epsilon = 0.0001
...>
...> cond do
...> abs(difference) < epsilon -> :ok
...> difference > 0.0 -> :low
...> difference < 0.0 -> :high
...> end
...> end
iex>
iex> {:ok, result} = Algorithms.binary_search(1, 100, solve, 0.0, :interval)
iex> Float.round(result, 6)
10.311285