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

Link to this section Types

Link to this type

binary_interval_search_fit_func()

View Source
binary_interval_search_fit_func() ::
  (binary_interval_search_position(), any() -> :ok | :high | :low)
Link to this type

binary_interval_search_position()

View Source
binary_interval_search_position() :: number()
Link to this type

binary_interval_search_result()

View Source
binary_interval_search_result() ::
  {:ok, binary_interval_search_position()} | :not_found
Link to this type

binary_search_fit_func()

View Source
binary_search_fit_func() ::
  (binary_search_position(), any() -> :ok | :high | :low)
Link to this type

binary_search_position()

View Source
binary_search_position() :: integer()
Link to this type

binary_search_result()

View Source
binary_search_result() :: {:ok, binary_search_position()} | :not_found
Link to this type

binary_search_strategy()

View Source
binary_search_strategy() :: :midpoint | :interval

Link to this section Functions

Link to this function

binary_search(start, finish, fit, target, strategy \\ :midpoint)

View Source
Link to this function

hybrid_binary_search(range_list, fit, target, strategy \\ :midpoint)

View Source

binary_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