Skip to content

Instantly share code, notes, and snippets.

@Janiczek
Created July 17, 2012 23:59
Show Gist options
  • Select an option

  • Save Janiczek/3133037 to your computer and use it in GitHub Desktop.

Select an option

Save Janiczek/3133037 to your computer and use it in GitHub Desktop.
Binary search in Erlang
%% I wondered if I'm in the 10% of devs that can write binary search correctly:
%% http://reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/
%% The automated test cases at http://www.mac-guyver.com/switham/2010/04/Binary_Search/
%% (edited for Erlang below) say I am. Well, nice to know :)
-module(binary_search).
-export([binary_search/2]).
-include_lib("eunit/include/eunit.hrl").
binary_search(List, N) ->
Length = length(List),
Middle = (Length + 1) div 2, %% saves us hassle with odd/even indexes
case Middle of
0 -> -1; %% empty list -> item not found
_ ->
Item = lists:nth(Middle, List),
case Item of
N -> Middle; %% yay, found it!
_ -> case Item > N of
true -> binary_search(lists:sublist(List, Length - Middle), N); %% LT, search on left side
false -> binary_search(lists:nthtail(Middle, List), N) %% GT, search on right side
end
end
end.
run:
erlc binary_search.erl
erl -noshell -s binary_search test -s init stop
tests:
python write_tests.py >binary_search_tests.erl
erlc binary_search_tests.erl
all: tests run
$ make all
python write_tests.py >binary_search_tests.erl
erlc binary_search_tests.erl
erlc binary_search.erl
erl -noshell -s binary_search test -s init stop
All 4096 tests passed.
#!/usr/bin/env python
# based on http://www.mac-guyver.com/switham/2010/04/Binary_Search/
# edited for Erlang :)
# now essentially prints out a file with all the EUnit tests
from random import *
# 0.0 <= random() < 1.0; a <= randrange( a, b ) < b for int(a) < int(b).
if __name__ == "__main__":
print "-module(binary_search_tests)."
print "-include_lib(\"eunit/include/eunit.hrl\")."
print
for n in range( 1, 4097 ):
size = int( 2.0 ** (random() * 8) - 1 ) # size can be zero.
if random() < .5:
A = range( size ) # every number in range
else:
A = [ randrange(size) for i in range(size) ] # random numbers
A.sort()
want_there = size > 0 and random() < .5
if want_there:
T = A[ randrange(size) ]
else:
theres = dict( [ ( x, True ) for x in A ] )
not_theres = [ x for x in range( -1, size+1 ) if not x in theres ]
T = not_theres[ randrange( len(not_theres) ) ]
is_there = T in A
assert( is_there == want_there )
print "a_%d_test() ->" % (n)
print " ?assert%s(binary_search:binary_search(%s, %d) =:= -1)." % (["","Not"][is_there], A, T)
print
@wang-zhijun
Copy link

It seems like this solution does not return the index of the element. So I created another one based on your solution which returns the index.

https://gist.github.com/ColdFreak/888e9a0a5cbed5ddc1a3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment