# Are you one of the 10% of programmers who can write a binary search?

There are some programming books that I’ve read from cover to cover repeatedly; there are others that I have dipped into many times, reading a chapter or so at a time.  Jon Bentley’s 1986 classic Programming Pearls is a rare case where both of these are true, as the scuffs at the bottom of my copy’s cover attest:

(I have the First Edition [amazon.comamazon.co.uk], so that’s what I scanned for the cover image above, but it would probably make more sense to get the newer and cheaper Second Edition [amazon.comamazon.co.uk] which apparently has three additional chapters.)

I’ll review this book properly in a forthcoming article (as I did for Coders at Work, The Elements of Programming Style, Programming the Commodore 64 and The C Programming Language), but for now I want to look at just one passage from the book, and consider what it means.  One astounding passage.

## Only 10% of programmers can write a binary search

Every single time I read Programming Pearls, this passage brings me up short:

Binary search solves the problem [of searching within a pre-sorted array] by keeping track of a range within the array in which T [i.e. the sought value] must be if it is anywhere in the array.  Initially, the range is the entire array.  The range is shrunk by comparing its middle element to T and discarding half the range.  The process continues until T is discovered in the array, or until the range in which it must lie is known to be empty.  In an N-element table, the search uses roughly log(2) N comparisons.

Most programmers think that with the above description in hand, writing the code is easy; they’re wrong.  The only way you’ll believe this is by putting down this column right now and writing the code yourself.  Try it.

I’ve assigned this problem in courses at Bell Labs and IBM.  Professional programmers had a couple of hours to convert the above description into a program in the language of their choice; a high-level pseudocode was fine.  At the end of the specified time, almost all the programmers reported that they had correct code for the task.  We would then take thirty minutes to examine their code, which the programmers did with test cases.  In several classes and with over a hundred programmers, the results varied little: ninety percent of the programmers found bugs in their programs (and I wasn’t always convinced of the correctness of the code in which no bugs were found).

I was amazed: given ample time, only about ten percent of professional programmers were able to get this small program right.  But they aren’t the only ones to find this task difficult: in the history in Section 6.2.1 of his Sorting and Searching, Knuth points out that while the first binary search was published in 1946, the first published binary search without bugs did not appear until 1962.

— Jon Bentley, Programming Pearls (1st edition), pp. 35-36.

Several hours!  Ninety percent!  Dude, SRSLY!  Isn’t that terrifying?

One of the reasons I’d like to see a copy of the Second Edition is to see whether this passage has changed — whether the numbers improved between 1986 and the Second-Edition date of 1999.  My gut tells me that the numbers must have improved, that things can’t be that bad;  yet logic tells me that in an age when programmers spend more time plugging libraries together than writing actual code, core algorithmic skills are likely if anything to have declined.  And remember, these were not doofus programmers that Bentley was working with: they were professionals at Bell Labs and IBM.  You’d expect them to be well ahead of the curve.

## And so, the Great Binary Search Experiment

I would like you, if you would, to go away and do the exercise right now.  (Well, not right now.  Finish reading this article first!)  I am confident that nearly everyone who reads this blog is already familiar with the binary search algorithm, but for those of you who are not, Bentley’s description above should suffice.  Please fire up an editor buffer, and write a binary search routine.  When you’ve decided it’s correct, commit to that version.  Then test it, and tell me in the comments below whether you got it right first time.  Surely — surely — we can beat Bentley’s 10% hit-rate?

Here are the rules:

1. Use whatever programming language you like.
2. No cutting, pasting or otherwise copying code.  Don’t even look at other binary search code until you’re done.
3. I need hardly say, no calling bsearch(), or otherwise cheating :-)
4. Take as long as you like — you might finish, and feel confident in your code, after five minutes; or you’re welcome to take eight hours if you want (if you have the time to spare).
5. You’re allowed to use your compiler to shake out mechanical bugs such as syntax errors or failure to initialise variables, but …
6. NO TESTING until after you’ve decided your program is correct.
7. Finally, the most important one: if you decide to begin this exercise, then you must report — either to say that you succeeded, failed or abandoned the attempt.  Otherwise the figures will be skewed towards success.

(For the purposes of this exercise, the possibility of numeric overflow in index calculations can be ignored.  That condition is described here but DO NOT FOLLOW THAT LINK until after writing your program, if you’re participating, because the article contains a correct binary search implementation that you don’t want to see before working on your clean-room implementation.)

If your code does turn out to be correct, and if you wish, you’re welcome to paste that code into your comment …  But if you do, and if a subsequent commenter points out a bug in it, you need to be prepared to deal with the public shame :-)

For extra credit: those of you who are really confident in your programming chops may write the program, publish it in a comment here and then test it.  If you do that, you’ll probably want to mention the fact in your comment, so we cut you extra slack when we find your bugs.

I will of course summarise the results of this exercise — let’s say, in one week’s time.

Let’s go!

## Update (an hour and a half later)

Thanks for the many posted entries already!  I should have warned you that the WordPress comment system interprets HTML, and so eats code fragments like

if a[mid] < value

The best way to avoid this is to wrap your source code in {source}…{/source} tags, but using square brackets rather than curly.  (The first time I tried to tell you all this, I used literal square brackets, and my markup-circumvention instructions were themselves marked up — D’oh!).  Do not manually escape < and > as &lt; and &gt; — the {source} wrapper deals with these.  Doing it this way also has the benefit of preserving indentation, which no other method seems to do.

And an apology for WordPress: I really, really wish that this platform allowed commenters to preview their comments and/or edit them after posting, so that all the screwed-up source code could have been avoided.  I’ve tried to go and fix some of them myself, but — arrgh! — it turns out that WordPress not only displays code with < symbols wrongly, it actually throws away what follows, so there’s nothing for me to restore.

## Update 2 (four hours after the initial post)

Wow, you guys are amazing.  Four hours, and this post already has more comments than the previous record holder (Whatever Happened to Programming, 206 comments at the time of writing.)

For anyone who’d like to see more discussion, there are some good comments at Hacker News and perhaps some slightly less insightful comments at Reddit, where actually writing code is seen as “elitism”.

## Update 3: links to this whole series

### 1,011 responses to “Are you one of the 10% of programmers who can write a binary search?”

1. I have the second edition and can tell you that the section you quoted above is essentially unchanged. The reference to IBM and Bell Labs was replaced by the more general “I’ve assigned this problem in courses for professional programmers” but the numbers are still there.

2. int binarySearch(int[] a, int value) {
int low = 0;
int high = a.length – 1;

while (low <= high) {
int mid = low + (high – low)/2;
int midValue = a[mid];

if (value midValue) {
low = mid + 1;
} else {
return mid;
}
}

return -1;
}

(not tested, typed in comment box)

3. Matt

Gah, once I hit “put down this column and write the code yourself”, I did. Failed to read the rules that said don’t test it. So essentially, I failed by not reading specifications, which is probably just as bad.

4. Jak

Implementation:

<?php

\$a = array();
\$k = 10;
for (\$i = 0; \$i < 500; \$i++) {
\$k += rand(1,20);
\$a[] = \$k;
}

foreach (\$a as \$v) {
echo \$v.' ';
}
echo "\n";

for (\$i = 0; \$i \$right) {
return false;
}
\$k = floor((\$left+\$right)/2.0);
if (\$array[\$k] == \$lookfor) {
return \$k;
}
if (\$array[\$k] > \$lookfor) {
return search(\$array, \$left, \$k-1, \$lookfor);
}
return search(\$array, \$k+1, \$right, \$lookfor);
}
?>

Correct on first run, according to the included test cases. Bug reports welcome.

5. Seemed to work for a couple quick tests, but blew up when searching for something that wasn’t in the list.

def bsearch_helper(list, target, low, hi):
if low > hi:
return None

mid = (low + hi) / 2

m = list[mid]

c = cmp(m, target)

if c == 0:
return mid
elif c < 0:
return bsearch_helper(list, target, mid + 1, hi)
else:
return bsearch_helper(list, target, low, mid – 1)

def bsearch(list, target):
return bsearch_helper(list, target, 0, len(list))

6. Hmmm, HTML fail. Let’s try again.

```int binarySearch(int[] a, int value) {
int low = 0;
int high = a.length – 1;

while (low <= high) {
int mid = low + (high – low)/2;
int midValue = a[mid];

if (value < midValue) {
high = mid - 1;
} else if (value > midValue) {
low = mid + 1;
} else {
return mid;
}
}

return -1;
}
```

(not tested, typed in comment box)

7. Matt

Code below for any more crowdsourced debugging:

int search(int term, int * array, int size) {
int mid = size / 2;
if (array[mid] > term) return search(term, array, mid);
if (array[mid] < term) return mid + search(term, array + mid, size – mid);
return mid;
}

8. Andres Holzer-Torres

Success. Altho I did it recursively.

Has been tested:
static int binarySearch(int[] values, int val) throws Exception
{
return binarySearchHelp(values, val, 0, values.length – 1);
}

static int binarySearchHelp(int[] values, int val, int start, int end)
throws Exception
{
if (start > end)
throw new Exception(“Somehow indexes have gotten reversed”);
if (start == end)
return values[start]==val ? start : -1;
int mid = (start + end) / 2;
if (values[mid] > val)
return binarySearchHelp(values, val, start, mid);
else if (values[mid] < val)
return binarySearchHelp(values, val, mid + 1, end);
else
return values[mid]==val ? mid : -1;
}

9. Josh
```def helper(array, low, high, x):
if low > high:
return False
if low == high:
return array[low] == x
mid = (low + high) / 2
if array[mid] == x:
return mid
elif array[mid] > x:
helper(array, low, mid, x):
else:
helper(array, mid, high, x):

def sort(array, x):
helper(array, 0, len(array) - 1)

```
10. @Josh: You sometimes return a boolean (False) and sometimes an integer (mid). Assuming you meant to return True instead of mid, you risk an infinite loop because you don’t guarantee that your interval gets smaller each step.

11. Don’t forget to account for numbers outside the range of your sorted array. I forgot it in my first attempt, so searching for something less than the first element or greater than the last would result in an infinite loop!

def find(list, n)
mid = (list.size / 2).ceil
target = list[mid]

# Arg, I failed!
return false if n > list.last || n target
return find(list[mid,list.size],n)
end
if n < target
return find(list[0,mid],n)
end

true
end

list = (0..1001).to_a

puts find(list,500)
puts find(list,list.first)
puts find(list,list.last)
puts find(list,1000)
puts find(list,33)
puts find(list,-1)
puts find(list,1002)

12. Code here:

http://pastebin.com/ms6BYwyy

I was not confident enough to post it without testing, and rightly so because I had a bug because I wrote the code in a way that seemed very elegant to me but that turned out to loop forever.

The original comparison was:

if (array[h] = x) hi = h + 1;

Which would terminate the loop immediately if it so happened that array[h] == x, but which would lead to an infinite loop if the interval was 2 elements large with the first element smaller than the search value and the second element larger (as with my first test case).

Time taken: 10 minutes.

13. I wrote it, and when I was sure it worked, I tested it. Not a single correction had to be made. Recursive algorithms are easy to think. I would have probably failed writing an iterative version.

bool binSearch(std::vector const &v, int key, int first, int last)
{
if (last – first == 1)
return v[first] == key;

int mid = (first+last)/2;
if (key < v[mid])
{
return binSearch(v, key, first, mid);
}
else
{
return binSearch(v, key, mid, last);
}
}

14. Argh, it seems smaller-than and greater-than signs are not escaped.

` if (array[h] x) hi = h;`

15. JWP

I fail. Buggy as crap. I bring shame to professional programmers everywhere.

```#!/usr/bin/python

def bfind(value, seq, start, end):
print 'bfind(%s, %s, %s, %s)' % (value, seq, start, end)
if start == end:
if seq[start] == value:
return start
else:
return None
else:
pivot = start + (end - start) / 2
middle = seq[pivot]
print 'pivot=%s, middle=%s' % (pivot, middle)
if middle == value:
return pivot
elif middle >= value:
return bfind(value, seq, start, pivot - 1)
else:
return bfind(value, seq, pivot + 1, start)

tests = [
(3, range(5), 4),
(7, range(50), 6),
(26, range(50), 25),
(99, range(50), None),
(-1, range(50), None),
(1, range(3), 2),
(1, [], None),
]

for value, seq, result in tests:
print '-' * 40
print 'looking for %s in %s elements' % (value, len(seq))
print bfind(value, seq, 0, len(seq) - 1)
```
16. dpirch

int bs(int len, int array[len], int t)
{
int start = 0, end = len;
while (start < end) {
int m = (start + end) / 2;
if (array[m] t) end = m;
else return m;
}
return -1;
}

17. int binarySearch(int array[], int value, int low, int high)

if(low > high)
return -1;

int midPoint = low + (high-low)/2;
int midValue = array[midPoint];

if(value == midValue) {
return midPoint;
}else if(value > midValue) {
return binarySearch(array, value, midPoint+1, high);
}else {
return binarySearch(array, value, low, midPoint-1);
}
}

// Didn’t test it. Just used pen and paper.
// This could stackoverflow if the compiler
// doesn’t support tail recursion.

18. Wrote it in Emacs (with SLIME), committed (^X ^E), fixed one syntax error (LET -> LET*), then hand-tested with a few corner cases in the REPL. I think I got it right, but I feel strangely unconfident…

```(defun binary-search (array value &key (start 0) (end (length array)))
"Return the index of value in the sorted array if it exists.  Otherwise return nil.  The search range is [start, end)."
(when (= start end)
(return-from binary-search nil))
(let* ((mid (floor (+ start
(/ (- end start)
2))))
(mid-val (elt array mid)))
(cond
;; Base-case 2: found.
((= value mid-val)
mid)
;; Search left in range [start, mid).
((< value mid-val)
(binary-search array value :start start :end mid))
;; Search right in range (mid, end).
(t
(binary-search array value :start (1+ mid) :end end)))))
```
19. VB.NET – I did get it wrong the first time, I had the upper and lower reversed when I was checking the startpoint.

Dim numarray(19) As Integer
Dim t As Integer = 7

numarray(0) = 1
numarray(1) = 2
numarray(2) = 3
numarray(3) = 4
numarray(4) = 5
numarray(5) = 6
numarray(6) = 7
numarray(7) = 8
numarray(8) = 9
numarray(9) = 10
numarray(10) = 11
numarray(11) = 12
numarray(12) = 13
numarray(13) = 14
numarray(14) = 15
numarray(15) = 16
numarray(16) = 17
numarray(17) = 18
numarray(18) = 19
numarray(19) = 20

Dim startpoint As Integer
Dim lower = 0
Dim upper = 19

Do
startpoint = (lower + upper) \ 2

If numarray(startpoint) = t Then
Debug.Print(“found it”)
Exit Do
End If

If upper = lower Then
Exit Do
End If
If numarray(startpoint) < t Then
lower = startpoint
Else
upper = startpoint
End If

Loop

20. Josh

@Lawrence Kesteloot I mean to return False if it’s not found, otherwise return the index where it is found, similar to how you return a -1. I’m still prepared to don my ribbons of shame.

21. pfarrell

NO TESTING until after you’ve decided your “program is correct.”

Who cares what the results are with this rule in place? You’re not measuring anything that applies to real world development.

Next, you’ll tell me only 10% of programmers produce x lines of code per year.

22. dpirch

first posting messed up by html, trying again

```int bs(int len, int array[len], int t)
{
int start = 0, end = len;
while (start < end) {
int m = (start + end) / 2;
if (array[m] < t) start = m + 1;
else if (array[m] > t) end = m;
else return m;
}
return -1;
}```
23. marshalium

This was my first attempt. I haven’t discovered any bugs yet.

```def b_search_helper(array, target, high, low):
middle = low + ((high - low) / 2)

if array[middle] == target:
return middle
elif array[middle]  target:
high = middle - 1

if high < low:
return -1

return b_search_helper(array, target, high, low)

def b_search(array, target):
return b_search_helper(array, target, len(array) - 1, 0)
```
24. horia
```int bsearch(int* h, int l, int n) {
if (l <= 0) {
return -1;
} else {
int m1 = l / 2;
int m2 = l / 2 + 1;

if (n == h[m1])       return m1;
else if (n < h[m1]) return bsearch(h,m1,n);
else                             return bsearch(h+m2,l-m2,n);
}
}
```

Thought about this a little bit more, since you said I was likely to screw it up. I’ll test it after I submit, since that seems to be the spirit of the exercise.
Hope I don’t blow it :)

25. Patrick Shields

Wrote a recursive solution in python with more or less no error checking. Worked until I changed from printing results to returning them and forgot to make the recursive calls return statements. Otherwise working fairly well. What am I missing?

This probably won’t look pretty:
def bsearch(listy, val, index):
if len(listy) == 1:
if listy[0] != val:
print “ERRRRRRRRRRRRROOOOOOOOOOOOOOORRRRRRRRRRRRRRRRRRRRRR”
return -1
else:
return index
else:
new_ind = len(listy)/2
if listy[new_ind] == val:
return index+new_ind
elif listy[new_ind] < val:
return(bsearch(listy[new_ind+1:], val, index+new_ind+1))
else:
return(bsearch(listy[:new_ind], val, index))

26. @Josh: If you want to return False, then the case of “low == high” is wrong because it returns “array[low] == x”. I think you can just remove that case altogether as long as you fix the recursion parameters.

@Daniel: Looks good.

27. ##Woohoo!! Got right the first time:)
def bsearch(arr,key,start=0,end=None):
if end == None: end = len(arr) – 1
if start > end: return None
if start == end and arr[start] != key: return None

mid = (start+end)/2
if arr[mid] == key:
return mid
if arr[mid] > key:
return bsearch(arr,key,start,mid-1)
if arr[mid] < key:
return bsearch(arr,key,mid+1,end)

28. Don’t forget to account for numbers outside the range of your sorted array. I forgot it in my first attempt, so searching for something less than the first element or greater than the last would result in an infinite loop!

```def find(list, n)
mid = (list.size / 2).ceil
target = list[mid]

# Arg, I failed!
return false if n > list.last || n < list.first

if n > target
return find(list[mid,list.size],n)
end
if n < target
return find(list[0,mid],n)
end

true
end

list = (0..1001).to_a
# these should be true:
puts find(list,500)
puts find(list,list.first)
puts find(list,list.last)
puts find(list,1000)
puts find(list,33)

# these should be false:
puts find(list,-1)
puts find(list,1002)```

Note: Duh, fixed for html

29. Time taken: 8 minutes

Result: failed. My original attempt had “end = mid – 1” instead of “end = mid”. That’s the only change I made from the original version.

Total testing/fixing time: 5 minutes

So 13 minutes total. I wouldn’t be horribly surprised if there are more bugs in there…

int bsearch_int( const int * values, const size_t n, const int key )
{
int begin = 0;
int end = n;

while( begin < end )
{
const int mid = begin + (end-begin)/2;
const int midval = values[mid];
if( key midval )
begin = mid + 1;
else
return mid;
}

return -1;
}

30. ```def bsearch(t, arr, a=0, b=arr.length-1)
while a <= b
m = (a+b)/2
x = arr[m]

if x == t
return m
elsif x > t
b = m-1
else # x < t
a = m+1
end
end

return false
end
```

a and b were initialised in the body but then I saw Lisp version :)

Ruby and other high-level languages are like high level pseudocode so that’s why it’s easy (but you can trip yourself if you don’t test carefully). Hope I got it right :)

31. I wasn’t going to bother posting, but since the only Python versions so far are recursive, here’s a really awful “whipped up in five minutes” iterative version. Hopefully, WP won’t mangle this too badly.

```def bsearch(range, target):
crange = range
offset = 0
while True:
ctarget = len(crange) / 2
if crange[ctarget] == target:
return ctarget + offset
elif crange[ctarget] > target:
crange = crange[:ctarget]
else:
crange = crange[ctarget+1:]
offset += ctarget+1
if len(crange) == 0:
return -1```
32. gwenhwyfaer

Well. First go, I wrote this:

long *binsearch( long *ary, long sz, long item)
{
if( 0 == sz ) return NULL; /* 0-length array */
if( ary[ sz>>1 ] == item ) return &ary[ sz>>1 ];
if( ary[ sz>>1 ] >1 ], sz>>1 + sz&1 – 1, item );
return binsearch( ary, sz>>1, item );
}

I was convinced that the logic was sound. C disagreed. Not being a daily user of C, it took me a while to figure it out… for reference, here’s the corrected version:

long *binsearch( long *ary, long sz, long item)
{
if( 0 == sz ) return NULL; /* 0-length array */
if( ary[ sz>>1 ] == item ) return &ary[ sz>>1 ];
if( ary[ sz>>1 ] >1 ], sz>>1 + (sz&1) – 1, item );
return binsearch( ary, sz>>1, item );
}

33. Python indentation is wrong in the previous submission!!!

I have put up my code at

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 def bsearch(arr,key,start=0,end=None): if end == None: end = len(arr) – 1 if start > end: return None if start == end and arr[start] != key: return None mid = (start+end)/2 if arr[mid] == key: return mid if arr[mid] > key: return bsearch(arr,key,start,mid–1) if arr[mid] < key: return bsearch(arr,key,mid+1,end)

view raw

bsearch.py

hosted with ❤ by GitHub

34. Erm, nevermind, looks like someone else already posted one. :)

35. hexphreak
```int bsearch( int v[ ], int s, int e )
{
int a = 0, b = s - 1, i;

do
{
i = ( b + a + 1 ) / 2;

if( v[ i ] > e )  b = i;
else  a = i;
}
while( v[ i ] != e && a < b );

if( v[ i ] == e )  return i;

return -1;
}```

Tested with first/middle/last element in even-/odd-size arrays. Works as far as I can tell.

36. travis

python example, only cursory testing so far so be gentle:

def bsearch(lst, item):
bottom, top = 0, len(lst)

while top – bottom >= 3:
mid = (top + bottom) // 2

c = cmp(item, lst[mid])

if c 0:
bottom = mid + 1
else:
return True

if item == lst[bottom]:
return True

return top – bottom == 2 and item == lst[bottom + 1]

37. I’ll throw in my extremely unoptimized php version, just to represent the web dudes… (And yes, I tested it)

2)
{
\$iMiddle = round(\$iArraySize/2);
}
elseif(\$iArraySize == 2)
{
\$iMiddle = 0;
}
else
{
\$bQuit = true;
print “\nRan out of values, is the answer: \$aItems[0]?”;
exit();
}

\$iTestValue = \$aItems[\$iMiddle];

print “Testing round \$i”;
print “\nArray size: ” . \$iArraySize;
print “\nMiddle of Array: ” . \$iMiddle;
print “\nLooking for Value ” . \$iVal;
print “\nFound Value: ” . \$iTestValue;

if(\$iTestValue == \$iVal)
{
//yay we found it!
print “\nYay they match!”;
\$bQuit = true;
}
else
{
if(\$iArraySize > 2)
{
if(\$iTestValue > \$iVal)
{
\$aItems = array_slice(\$aItems, 0, \$iMiddle);
}
else
{
\$aItems = array_slice(\$aItems, \$iMiddle );
}
}
else
{
\$aItems = array(\$aItems[1]);
}
}

}

?>

38. gwenhwyfaer

Damn. HTML munched my code. :(

39. KG

Untested (but compiled). Scrolling down to the comment box, I couldn’t help but glance at the other submissions. Fortunately, due to their similarity, that only increased my faith in my own attempt. Perhaps it would be best if they were somehow hidden for the next week, though…

I wish there were a comment preview – no idea whether this will be formatted correctly.

```	static public <T extends Comparable> int binarySearch(List haystack, T needle)
{
int min = 0;
int max = haystack.size() - 1;
while(max >= min)
{
int next = (min + max) / 2;
int cmp = needle.compareTo(haystack.get(next));
if(cmp == 0)
return next;
if(cmp < 0)
max = next - 1;
else
min = next + 1;
}
return -1;
}
```
40. 2)
{
\$iMiddle = round(\$iArraySize/2);
}
elseif(\$iArraySize == 2)
{
\$iMiddle = 0;
}
else
{
\$bQuit = true;
print “\nRan out of values, is the answer: \$aItems[0]?”;
exit();
}

\$iTestValue = \$aItems[\$iMiddle];

print “Testing round \$i”;
print “\nArray size: ” . \$iArraySize;
print “\nMiddle of Array: ” . \$iMiddle;
print “\nLooking for Value ” . \$iVal;
print “\nFound Value: ” . \$iTestValue;

if(\$iTestValue == \$iVal)
{
//yay we found it!
print “\nYay they match!”;
\$bQuit = true;
}
else
{
if(\$iArraySize > 2)
{
if(\$iTestValue > \$iVal)
{
\$aItems = array_slice(\$aItems, 0, \$iMiddle);
}
else
{
\$aItems = array_slice(\$aItems, \$iMiddle );
}
}
else
{
\$aItems = array(\$aItems[1]);
}
}

}

? >

Let’s try that again…

41. hexphreak

Okay, it doesn’t. Screws up for values less than the array minimum. Ah, well.

42. gwenhwyfaer
```long *binsearch( long *ary, long sz, long item)
{
if( 0 == sz ) return NULL; /* 0-length array */
if( ary[ sz>>1 ] == item ) return &ary[ sz>>1 ];
if( ary[ sz>>1 ] >1 ], sz>>1 + (sz&1) - 1, item );
return binsearch( ary, sz>>1, item );
}
```
43. Andrew Queisser

That was fun – I took about 10 minutes and couldn’t wait to try it so I failed the test. I’m in the 90%. My submission has two problems, it compares the value to the index instead of the value and it doesn’t terminate when the value isn’t there. Both problems were easily fixed once I identified them.

#include
#include

static int data[10000];

{
FILE *fp = fopen(fname, “r”);
int dc = 0;
int *dp = data;
if (fp)
{
while (fscanf(fp, “%d”, dp) > 0)
dp++;
dc = dp-data;
}

return dc;
}

int main(int argc, char **argv)
{
int target = atoi(argv[2]);
int bot = 0;
int top = count-1;
int pivot;
int found = 0;

if (count == 0)
return -1;

while (!found && bot != top)
{
pivot = (bot+top)/2;
printf(“[%d] %d [%d] %d [%d] %d\n”, bot, data[bot], pivot, data[pivot], top, data[top]);
if (target > data[pivot])
bot = pivot;
else if (target < data[pivot])
top = pivot;
else
{
printf("found %d at index %d\n", target, pivot);
found = 1;
}
}

return found;
}

44. Geoff

I attempted and failed. I instinctively hit the “Run” button before I was actually done, because it’s so ingrained to test the code at each step.

45. How do we know if we pass?

46. bl

[ int BinarySearch(int value,int low, int hi, int[] list) {
var middle=((hi-low) / 2)+low;

if (hi<=low||list[middle]==value) {
return (list[middle]==value ? middle : -1);
}
if(list[middle]value) {
return BinarySearch(value, low, middle-1, list);
}
return -1;
}]

47. marshalium

Most of my previous comment got eaten. This is what worked for me.

```def b_search_helper(array, target, high, low):
middle = low + ((high - low) / 2)

if array[middle] == target:
return middle
elif array[middle] < target:
low = middle + 1
elif array[middle] > target:
high = middle - 1

if high < low:
return -1

return b_search_helper(array, target, high, low)

def b_search(array, target):
return b_search_helper(array, target, len(array) - 1, 0)
```
48. horia

Bugfixing

```int
myBSearch (int* h, int l, int n)
{
if (l <= 0) {
return -1;
} else {
int m1 = l / 2;
int m2 = l / 2 + 1;

if (n == h[m1]) {
return m1;
} else if (n < h[m1]) {
return myBSearch(h,m1,n);
} else {
int r = myBSearch(h+m2,l-m2,n);
if (r == -1) {
return -1;
} else {
return m2 + r;
}
}
}
}
```
49. Sorry, don’t count mine, I did test it. I recognise I am not able to “code on paper”, that’s no news for me :)

50. travis
51. Well, mine turned out a bit wordier than a lot of other people’s… bad programmer! (and to think I taught myself coding in the age of 16K machines with cassette drives… I’ve gotten fat and lazy.)

Like many others, I return the index location if it’s found and -1 if it’s not.

Thought of doing it recursively, which would be more elegant, but just went for the most straightforward brute-force approach. Hopefully, it actually works for all cases.

java.lang.String items[]=new String[50];//0 indexed
int arraylength=items.length-1;
boolean found=false;
int lowbound=0;
int midpoint=-1;
int highbound=arraylength;
int foundIndex=-1;
for(int i=0;i<50;i++)
{
items[i]=String.valueOf(i);
}
Arrays.sort(items);
String item2find=new String("30");
int passes=0;
while(!found)
{
//first, see if object can exist in range
passes++;
if ((item2find.compareTo(items[lowbound])0))
{
found=true;
foundIndex=-1;
continue;
}
midpoint=lowbound+((highbound-lowbound)/2);

if(items[midpoint].equals(item2find))
{
found=true;
foundIndex=midpoint;
continue;
}
if(highbound==lowbound)
{
found=true;
foundIndex=-1;
continue;
}
if(item2find.compareTo(items[midpoint])<0)
{
highbound=midpoint-1;
}
else
{
lowbound=midpoint+1;
}
}
System.out.println(passes+" passes. Location:"+foundIndex);

In terms of "Worked on first try"… well, sortakinda. :) I needed to add arrays.sort. Once the array was, in fact, sorted, the algorithm SEEMS to work. If I put in an element that's not there, it returns -1, if I put in an element that is there, it finds it. I'm sure I'm missing something, I always do….

52. Domenico

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 from random import randint def bsearch(stuff, x, offset=0): if len(stuff) == 0: return –1 half = int(len(stuff) / 2) if stuff[half] == x: return half + offset elif x < stuff[half]: return bsearch(stuff[:half], x, offset) elif x > stuff[half]: return bsearch(stuff[half + 1:], x, offset + half + 1) def test(n=100, m=200): xs = [randint(0, n) for i in range(m)] xs.sort() y = randint(0, n) print ">>>", y i = bsearch(xs, y) if (i == –1 and y in xs) or (i != –1 and xs[i] != y): print "error ——————-" print y, i print xs print "————————-" else: print "ok" for i in range(100): test()

view raw

gistfile1.pyw

hosted with ❤ by GitHub

lo and behold, I run the test for the first time and… voila! here’s a bug!

I must admit it was a pure WTF moment, but the error turned out to be a typo — the program still parsed and ran, it just… well, didn’t work. ;)

53. gwenhwyfaer

Ah, screw it.

long *binsearch( long *ary, long sz, long item)
{
if( 0 == sz ) return NULL; /* 0-length array */
if( ary[ sz>>1 ] == item ) return &ary[ sz>>1 ];
if( ary[ sz>>1 ] < item ) return binsearch( &ary[ 1 + sz>>1 ], sz>>1 + sz&1 – 1, item );
return binsearch( ary, sz>>1, item );
}

54. PaulC

def bsearch(target,array,offset=0):
l = len(array)
if l == 0:
return False
elif l == 1:
if array[0] == target:
return offset
else:
return False
else:
midpos = l//2
midval = array[midpos]
if midval == target:
return offset + midpos
elif midval < target:
return bsearch(target,array[midpos:],offset+midpos)
else:
return bsearch(target,array[:midpos],offset)

55. PaulC

Again with formatting

```def bsearch(target,array,offset=0):
l = len(array)
if l == 0:
return False
elif l == 1:
if array[0] == target:
return offset
else:
return False
else:
midpos = l//2
midval = array[midpos]
if midval == target:
return offset + midpos
elif midval < target:
return bsearch(target,array[midpos:],offset+midpos)
else:
return bsearch(target,array[:midpos],offset)
```
56. Bah, markup ate my attempt. Here’s how it’s supposed to read: http://pastebay.com/94342

@mike, your instructions on how to circumvent wordpress’ markup got marked up itself, so it can’t be read…. :)

57. Mooneer Salem

#include
#include

int binary_search_helper(int *array, int search_from, int search_to, int needle)
{
int subset_length = search_to – search_from + 1;
int midpoint = search_from + subset_length / 2;

if (search_from == search_to)
{
if (needle == array[search_from]) return search_from;
return -1;
}
if (needle == array[midpoint]) return midpoint;

if (needle < array[midpoint] && midpoint != search_from) return binary_search_helper(array, search_from, midpoint – 1, needle);
else if (needle > array[midpoint] && midpoint != search_to) return binary_search_helper(array, midpoint + 1, search_to, needle);
else return -1;
}

int binary_search(int *array, int length, int needle)
{
return binary_search_helper(array, 0, length – 1, needle);
}

int main()
{
int array_odd[] = {1, 3, 4, 7, 9, 11, 102};
int array_even[] = {1, 3, 4, 7, 8, 9, 11, 102};
int index;

for (index = 0; index < 7; index++)
{
assert(binary_search(array_odd, 7, array_odd[index]) == index);
}

assert(binary_search(array_odd, 7, 1337) == -1);
assert(binary_search(array_odd, 7, -5) == -1);

for (index = 0; index < 8; index++)
{
assert(binary_search(array_even, 8, array_even[index]) == index);
}

assert(binary_search(array_even, 8, 1337) == -1);
assert(binary_search(array_even, 8, -5) == -1);

printf(“All tests pass.\n”);
return 0;
}

Output:

mooneer@voldemort:~\$ ./bsearch
All tests pass.
mooneer@voldemort:~\$

58. After 15 minutes: http://gist.github.com/371501

I wouldn’t be quite this defensive if I didn’t know of the problem’s reputation.

I haven’t bothered with local variables or default arguments.

59. gwenhwyfaer

So, my results? Well, I failed. I got the logic right, but got bitten by an arcane syntactical rule… because I chose a language I could test easily, but in which I am not quite fluent.

In fairness, though, it’s five years since I coded for a living.

60. pete gamache

My first crack at bsearch in Perl, and it seems to work. Compares strings only, for brevity.

``` # bsearch(\$elt, \$arrayref) performs a binary search on an array of # sorted strings. returns element index if \$elt is in @\$arrayref, # undef otherwise. sub bsearch { my (\$elt, \$arrayref, \$min_idx, \$max_idx) = @_; my \$nelts = scalar @\$arrayref; return undef unless \$nelts > 0; return undef if \$min_idx > \$max_idx;```

``` \$min_idx = 0 unless defined \$min_idx; \$max_idx = \$nelts-1 unless defined \$max_idx; my \$mid_idx = int((\$max_idx - \$min_idx) / 2) + \$min_idx; ```

``` if (\$elt eq \$arrayref->[\$mid_idx]) { return \$mid_idx; } elsif (\$elt lt \$arrayref->[\$mid_idx]) { return bsearch(\$elt, \$arrayref, \$min_idx, \$mid_idx-1); } else { return bsearch(\$elt, \$arrayref, \$mid_idx+1, \$max_idx); } } ```

61. Mooneer Salem

Gah, it stripped out the pre tag. http://pastebin.ca/1868406

Output is still “All tests pass.” :)

62. Pieter

Unfortunately, i failed because i swapped a < for a <= accidently.

63. Steffen Beyer

First try:

```# supposed to return the index of target in list
def bsearch(list, target)
loop do
return nil if list.empty?

middle = (list.length / 2).floor
left, pivot, right = list[0 .. middle - 1],
list[middle],
list[middle + 1 .. list.length - 1]

if pivot == target
return middle
elsif pivot < target
list = right
elsif pivot > target
list = left
else
warn 'nanu?'
end
end
end
```

After short testing:

```# supposed to return the index of target in list
def bsearch(list, target)
base = 0

loop do
return nil if list.empty?

middle = (list.length / 2).floor
left, pivot, right = list[0 .. middle - 1],
list[middle],
list[middle + 1 .. list.length - 1]

if pivot == target
return middle + base
elsif pivot < target
list = right
base = middle + 1
elsif pivot > target
list = left
else
warn 'nanu?'
end
end
end
```
64. Chester Grant

public static int search(int [] arr, int key){
if((arr.length == 0)||(arr ==null)){
return -1;
}
if(arr.length ==1){
if(arr[0] == key){
return 0;
}else{
return -1;
}
}
int left =0;
int right = arr.length-1;
int mid = (left+ right)/2;
boolean found = false;
while((left key){
left =mid+1;
mid = ((left+right)/2);
}else{
right = mid-1;
mid = ((left+right)/2);

}
}

if(found == false){
return -1;
}
return mid;

}

65. Sili

untested, php, w/ tail-recursion

recursion makes things like this easy

\$mB) return 1;
return -1;
}

function binSearch(\$aData, \$mSearchVal, \$iStart = -1, \$iEnd = -1) {
if (\$iStart == -1) { \$iStart = 0; \$iEnd = count(\$aData) -1; }

switch(\$iEnd – \$iStart) {
case 1:
if (0 == compare(\$aData[\$iEnd], \$mSearchVal)) return \$iEnd;
case 0:
if (0 == compare(\$aData[\$iStart], \$mSearchVal)) return \$iStart;
return false;
default:
\$iMidP = (\$iStart + \$iEnd) / 2;
if (0 == compare(\$aData[\$iMidP], \$mSearchVal)) return \$iMidP;
if (0

66. Dan

in python (no testing done):

def search(n, l):
H = len(l) – 1
L = 0
M = int(H / 2)

while H – L > 0 and n != l[M]:
if n > l[M]:
L = M
else:
H = M
M = int((H + L) / 2)

if n == l[M]:
return M

return -1

67. Alex Ungur

Just a simple, recursive Ruby solution. Hopefully correct too :-)

```#!/usr/bin/env ruby

def search(search_item, array, middle = array.size / 2, middle_val = array[middle])
return nil if search_item < array.first or search_item > array.last
return middle_val if middle_val.eql?(search_item)
search search_item, middle_val > search_item ? array[0,middle] : array[middle..-1]
end```
68. Robin Message

C, 10 minutes, no testing, fingers crossed…

[
int binary_search(int target,int* list,int start,int end) {
if(start==end)return -1;
if(list[start]==target)return start;
int mid=start+(end-start)/2;
if(list[mid]<target)return binary_search(target,list,mid+1,end);
else return binary_search(target,list,start,mid+1);
}

int bsearch(int target,int* list,int len) {
return binary_search(target,list,0,len);
}
]

69. Wrote it first, tested it afterwards, posting finally. As far as I can test it, no bugs found, and recognizes unavailable elements correctly. *phew*. Wrote and checked the code in 20 minutes or so. I Used Java List instead of arrays, since it’s easier to sort in my tests. But there’s no magical properties…

Did it recursively. Returns the index in which the element is, or throws a suitable exception if not found.

public static <T extends Comparable> int binarySearch(final T needle,
final List haystack) throws ElementNotFoundException {
return binarySearch(needle, haystack, 0, haystack.size() – 1);
}

private static <T extends Comparable> int binarySearch(final T needle,
final List haystack, final int left, final int right)
throws ElementNotFoundException {

if (left > right) {
throw new ElementNotFoundException();
}

final int center = ((right – left) / 2) + left;
final T elementAtCenter = haystack.get(center);

final int comparisonResult = elementAtCenter.compareTo(needle);

if (comparisonResult 0) {
return binarySearch(needle, haystack, left, center – 1);
} else {
return center;
}
}

70. Juan Pablo

Haven’t tested it at all:

```	int somethign (unsigned int haystack[], unsigned int size, unsigned int needle)
{
int lowerbound = 0;
int upperbound = size;

if (size == 0);
return INVALIDPARAMS;

for (;;) {
int middle = ((upperbound + lowerbound)/2);

if (needle == haystack[middle]) {
return middle;
}

if (upperbound == lowerbound)
{
return NOTFOUND;
}

if (needle &lt; haystack[middle]) {
upperbound = middle;
} else {
lowerbound = middle + 1;
}
}

return NOTFOUND;
}
```

I screwed it up. I tried to anticipate Python and integer-division rules (when ignoring them does the right thing instead), and so got infinite recursion.

Two minutes longer than it should have taken me. Blargh.

72. Ngh… formatting fail. Sorry about that. I didn’t know how to format the code properly :(

73. No testing done, except for making it compile right. Bash away :)

```int * bsearch(int * begin, int * end, int v)
{
if (end - begin == 1)
return (*begin == v) ? begin : (int*)0;

int * middle = begin + (end - begin) / 2;
if (*middle > v)
return bsearch(begin, middle, v);
else
return bsearch(middle, end, v);
}

int main()
{ // usage:
int array[] = { 1, 2, 4, 8, 16 };
int v = 3;

bsearch(array, array + 5, v);
return 0;
}
```
74. http://www.mistcat.com/binary_search.html
I can’t figure out your crazy wordpress code insertion magic…

75. Sili

php, w/ tail-recursion, now tested, worked first time

recursion makes things like this easy

previous html formatting fail
``` <?php function compare(\$mA, \$mB) { //modify as necessary comparing if (\$mA == \$mB) return 0; if (\$mA > \$mB) return 1; return -1; }```

``` function binSearch(\$aData, \$mSearchVal, \$iStart = -1, \$iEnd = -1) { if (\$iStart == -1) { \$iStart = 0; \$iEnd = count(\$aData) -1; } switch(\$iEnd - \$iStart) { case 1: if (0 == compare(\$aData[\$iEnd], \$mSearchVal)) return \$iEnd; case 0: if (0 == compare(\$aData[\$iStart], \$mSearchVal)) return \$iStart; return false; default: \$iMidP = (\$iStart + \$iEnd) / 2; if (0 == compare(\$aData[\$iMidP], \$mSearchVal)) return \$iMidP; if (0 < compare(\$aData[\$iMidP], \$mSearchVal)) return binSearch(\$aData, \$mSearchVal, \$iStart, \$iMidP - 1); return binSearch(\$aData, \$mSearchVal, \$iMidP + 1, \$iEnd); } } var_dump(binSearch(array(0, 5, 22, 412, 1234, 2134, 5432), 5)); ```

```?> ```

76. time taken: 8 minutes in ruby
bugs: at least 2 illuminated from comments above.

i guess i haven’t written a binary search since i was in algorithms class 15 years ago. no recollection as to whether that one turned out to be correct,.

at least i failed quickly?

77. xiccus

If I wrote this right, it has the added advantage of always returning the smallest correct index (so a search for 3 in [2, 3, 3, 3, 3, 3, 3, 4] will return 1).

int binsearch(int *arr, int len, int search) {
int *mid, at, left_len, right_len, val;
if (len <= 1) {
if (len == 1 && *arr == search) return 0;
return -1;
}
left_len = len/2;
right_len = len – left_len;
mid = arr + left_len;
val = *mid;
if (search <= val) {
at = binsearch(arr, left_len, search);
if (at = 0) at += left_len;
}
return at;
}

78. Python. I did test it, but I swear that I did not alter it after testing.

```def search(needle, l):
start, end = 0, len(l)-1

while start <= end:
mid = (start + end) / 2
if l[mid] == needle:
return mid
elif l[mid] < needle:
start = mid + 1
else:
end = mid - 1
return -1
```
79. Si

Python, iterative, passed all my tests so far (I’m probably missing something, though):

``` def bsearch(nums, item): while nums: mid = len(nums) / 2```

``` if nums[mid] > item: nums = nums[:mid] elif nums[mid] < item: nums = nums[mid+1:] else: return True ```

``` return False ```

I predict that more than 10% of programmers who read programming blogs will get this right.

80. Sam S
```
/**
* Searches an array sorted according to the given comparator for an element
* that is equal to obj according to the comparator, and returns the index
* of the matching element. If no such element exists, then returns -1. If
* more than one such element exists, then the index of any of the matching
* elements may be returned. If the array is not sorted according the the
* comparator, then false negatives may occur, but never false positives.
*
* Does not support null as any argument or any element of the supplied
* array.
*
* @param <T>
* @param array
* @param obj
* @param comparator
* @return
*/
public static <T> int binarySearch(T[] array, T obj, Comparator<? super T> comparator) {
int low = 0;
int high = array.length - 1;
while(high > low) {
int mid = (low+high)/2;
T midObj = array[mid];
int comparison = comparator.compare(obj, midObj);
if(comparison < 0) {
high = mid - 1;
}
else if(comparison > 0) {
low = mid + 1;
}
else {
return mid;
}
}
return -1;
}

```
81. Jamie

def binary_search(array,val,lowval=0,highval=array.size-1)
searchval = lowval + (highval-lowval)/2
if val > array[searchval]
lowval = searchval
binary_search(array,val,lowval,highval)
elsif val < array[searchval]
highval = searchval
binary_search(array,val,lowval,highval)
else
puts searchval
end
end

82. mos

Untested:

```template<typename raIterator, typename ltComparable>
bool bsearch(raIterator begin, raIterator end, const ltComparable &val)
{
while(begin != end)
{
raIterator mid = (end - begin) / 2;

if(*mid == val)
{
return true;
}

if(*mid < val)
{
begin = mid + 1;
}
else
{
end = mid;
}
}

return false;
}```
83. Emacs Lisp. No bugs found during testing.

(defun bsearch (vec elt)
“binary search VEC for ELT, returning index, or -1 if not found”
(bsearch-impl vec elt 0 (- (length vec) 1)))
(defun bsearch-impl (vec target left right)
(let ((mid (/ (+ left right) 2)))
(cond ((eq left right)
(if (eq target (elt vec left))
left
-1))
(( (elt vec mid)
(bsearch-impl vec target (+ 1 mid) right)))))

84. Andres Holzer-Torres

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 static int binarySearch(int[] values, int val) throws Exception { return binarySearchHelp(values, val, 0, values.length – 1); } static int binarySearchHelp(int[] values, int val, int start, int end) throws Exception { if (start > end) throw new Exception("Somehow indexes have gotten reversed"); if (start == end) return values[start]==val ? start : -1; int mid = (start + end) / 2; if (values[mid] > val) return binarySearchHelp(values, val, start, mid); else if (values[mid] < val) return binarySearchHelp(values, val, mid + 1, end); else return values[mid]==val ? mid : -1; }

Silly HTML eating my formatting . . . Still a success tho’.

85. Another one with Javascript, recursive.

```function bsearch(arry, item, beg, end)
{
var mid = Math.floor((end-beg)/2) + beg;

// found it
if(arry[mid] == item)
return mid;

if(mid == beg)
return -1;

// check "the orher side"
if(arry[mid] > item)
return bsearch(arry, item, beg, mid);
else
return bsearch(arry, item, mid, end);
}
```

After writing it, I did some rough testing and seems OK (but I may be wrong).

The surprising part it’s I’ve chosen Javascript. I need to think about it.

86. ```def binsearch(arr, val)

return nil if arr.empty?

lo = 0
hi = arr.size - 1

while true

if hi - lo  val
hi = center
elsif arr[center] < val
lo = center
end
end

end
```
87. Robin Message

Tried to be too clever,

```int mid=start+(end-start)/2;
if(list[mid]==target)return mid;
else if(list[mid]<target)return binary_search(target,list,mid+1,end);
else return binary_search(target,list,start,mid);
```

doesn’t go into an infinite loop…

88. Nathan H

[
def bsearch(sorted_array, given)
midpoint = sorted_array.length / 2
check = sorted_array[midpoint]
return check if given == check
return nil if sorted_array.length <= 1
unless given < check
bsearch sorted_array[(midpoint + 1)…sorted_array.length], given
else
besearch sorted_arry[0…midpoint], given
end
]

89. Si

2nd attempt, possibly with indentation this time. Python, iterative, passed all my tests so far.

```def bsearch(nums, item):
while nums:
mid = len(nums) / 2

if nums[mid] > item:
nums = nums[:mid]

elif nums[mid] < item:
nums = nums[mid+1:]

else:
return True

return False
```

I predict that more than 10% of programmers who read programming blogs will get this right. Apart from the formatting in comments.

90. I think it ate part of my post.

91. Here’s an updated post now that I can read how to mark up the code s.t. wordpress is happy.

Time taken: 8 minutes

Result: failed. My original attempt had “end = mid – 1″ instead of “end = mid”. That’s the only change I made from the original version.

Total testing/fixing time: 5 minutes

So 13 minutes total. After the off-by-one I mentioned above was fixed, it passed my tests and the other regression tests other people have posted in C… but still, my first version was a failure, so I fail the test. :)

```int binary_search( const int * values, const size_t n, const int key )
{
int begin = 0;
int end = n;

while( begin &lt; end )
{
const int mid = begin + (end-begin)/2;
const int midval = values[mid];

if( key  midval )
begin = mid + 1;
else
return mid;
}

return -1;
}
```
92. ``` /** * Returns index if found, -1 otherwise. */ int binarySearch(int[] array, int searched) { int start = 0, end = array.length; while (start searched) begin = middle + 1; else end = middle - 1; } return -1; } ```

Took me about half an hour. I’m in second year computer science and was introduced the algorithm last year, tough I never wrote one.

93. For fun, I wrote mine in Delphi:

```// return index of v in a, or -1 if not found
function Search(a: TArray<Integer>; v: Integer): Integer;
var
l, r, m: Integer;
begin
l := 0;
r := Length(a);
while l < r do
begin
m := l + (r - l) div 2;
// m < r, guaranteed => bad index won't happen
if a[m] = v then
Exit(m);
if v < a[m] then
r := m
else
l := m + 1;
end;
Result := -1;
end;
```
94. Sili

looked again, forgot to enforce typing
change line 22:
\$iMidP = (\$iStart + \$iEnd) / 2;
to:
\$iMidP = (int)((\$iStart + \$iEnd) / 2);

95. Jason

def binsearch(v, lst):
“””Find a value v in a sorted list lst, using a binary search algorithm.
“””
length = len(lst):
if length == 0:
return False
elif length == 1:
if lst[0] == v:
return True
else:
return False
else :
if not length%2:
tmp = length/2 + 1
else:
tmp = length/2
tmp_v = lst[tmp]
if tmp_v == v:
return True
if tmp_v < v:
return binsearch(v, lst[tmp:])
else:
return binsearch(v, lst[:tmp])

This was my original version, and I've found 1 bug, my +1 is on the wrong branch.

The no testing clause was a killer on this, because I'd normally do something like this with unit tests via TDD. So, I did not get a working version in my first cut, but would have if I had written it as I normally write code.

96. I had an off-by-one error for the new upper/lower bound, but other than that, I got it.

97. (ok the hmtl code tag was a bad idea apparently)
``` /** * Returns index if found, -1 otherwise. */ int binarySearch(int[] array, int searched) { int start = 0, end = array.length; while (start searched) begin = middle + 1; else end = middle - 1; } return -1; } ```

98. Sam S

Got my loop comparison wrong. I wrote

```while(high > low) {
```

while I should have written

```while(high >= low) {
```
99. b

Here’s mine, untested:

```	//called with 0 as lowerbound, searcharray.length - 1 as upperbound
public int binsearch(int searcharray[],int lowerbound, int upperbound, int target) {
if (lowerbound > upperbound) {
return -1;
}
int search = upperbound - lowerbound / 2;
if (searcharray[search] < target) {
return binsearch(searcharray,lowerbound,search - 1,target);)
} else if (searcharray[search] > target) {
return binsearch(searcharray,search+1,upperbound,target);
}
return search;
}
```

This is not the way I wrote it when assigned this 10 years ago in college (I’m pretty sure I had the non-recursive loop with 3 comparisons), but it is the way we were shown to do it after turning it in.
I’ve never had to do anything like this in my career to date, for whatever reason (probably because I’m a java developer working on web based apps).

100. Raphael

Fail.
Coded it in 10 minutes, not thinking enough, and forgot the +1/-1. Everything else is almost exactly like in the Google example. I incidentally even took care of index overflows :)

101. Nick Brown

Well, I’m clearly not ready to join the ranks of the great and good just yet… I got my “greater than” and “less than” the wrong way around. That amended, here it is, tested, as a Smalltalk method definition:

binarySearchFor: target in: array range: interval

| midIndex midValue |

interval size = 1 ifTrue: [
(array at: interval first) = target
ifTrue: [^interval first]
ifFalse: [^nil]
].

midIndex := interval first + (interval size // 2).
midValue := array at: midIndex.

midValue = target ifTrue: [
^midIndex
].

midValue > target ifTrue: [
^self binarySearchFor: target in: array range: (
interval first to: (midIndex – 1 max: interval first)
)
].

midValue < target ifTrue: [
^self binarySearchFor: target in: array range: (
(midIndex + 1 min: interval last) to: interval last
)
].

102. Not tested.

def search(list, val, start=0, end=None):
if not end: end = len(list)-1
if start>end:
return -1
middle = (end+start) / 2
if list[middle] == val:
return middle
if list[middle] val:
return search(list, val, start=start, end=middle-1)

103. I did manual testing by mentally stepping through my pseudocode with a few test inputs, which identified a couple of bugs that I fixed. Hope that is not cheating! After I decided that pseudocode was correct, here it is translated into Python:

```#!/usr/bin/env python

def bsearch(needle, haystack):
lower = 0
upper = len(haystack) - 1
idx = int(upper/2)
found = haystack[idx] == needle
if lower >= upper:
break
if needle > haystack[idx]:
lower = idx + 1
else:
upper = idx - 1
idx = int(.5 *(lower + upper))
found = haystack[idx] == needle
if found:
return idx # found it!
return False # indicating item not in the list

if '__main__' == __name__:
# uncomment your test input of choice
needle = 7
haystack = [1, 2, 3, 4, 6, 7]
#needle = 5
#haystack = [1, 4, 6, 9, 12]
#needle = 4
#haystack = [1, 4, 6, 9, 12]
print bsearch(needle, haystack)
```
104. Not tested:

```def search(list, val, start=0, end=None):
if not end: end = len(list)-1
if start>end:
return -1
middle = (end+start) / 2
if list[middle] == val:
return middle
if list[middle] < val:
return search(list, val, start=middle+1, end=end)
if list[middle] > val:
return search(list, val, start=start, end=middle-1)
```
105. CK

First attempt. C#. Worked in every test I could think of:

``` public static int? BinSearch(IEnumerable src, int target) { if (!src.Any()) return null;```

``` var n = (int)Math.Floor(src.Count() / 2d); var mid = src.ElementAt(n); ```

``` if (mid == target) return mid; if (mid < target) return BinSearch(src.Skip(n+1), target); return BinSearch(src.Take(n), target); } ```

106. Max

You didn’t seem to provide an email to contact you with, so I’ll comment here.

I wrote my response in Python, and there did turn out to be two bugs. One, I mixed up the label for the length of the incoming list and the label for the point to be searched, and two I forgot divide the length in half when I recursed. Ah well. Got it right in about ten minutes though, including the testing.

def bsearch(srtd,x):
l = len(srtd)
if l == 0:
return False
med = srtd[l/2]
print med
if med == x:
return True
if x < med:
return bsearch(srtd[:(l/2)],x)
else:
return bsearch(srtd[(l/2)+1:],x)

107. ~b

I started writing as soon as I saw “Try It”, so I tested it twice before really thinking “Okay it’s done”.

def find(value, ary)
subarray_find(value, ary, 0, ary.length-1)
end
def subarray_find(value, ary, bottom, top)
if top < bottom
return -1
end
pivot_loc = ((top+bottom)/2.0).floor
pivot_value = ary[pivot_loc]
if pivot_value == value
return pivot_loc
elsif pivot_value value
return subarray_find(value, ary, bottom, pivot_loc-1)
end
end

presorted_array = [0, 1, 2, 3, 4, 5, 6, 9, 11, 25]
presorted_array.each do |v|
puts find(v, presorted_array) #should result in printing 0-9
end
puts find(17, presorted_array) #-1
puts find(17, []) #-1

108. Luke V.

Here’s my impl in Clojure. Not tested. Takes a custom search function. Is susceptible to numerical overflow, but if you have that many elements in an in-memory data structure, you have other problems.

I’ll test it later on today if I get time. Is there a standard set of test conditions, anywhere? I’d hate to “pass” simply because I forgot an edge case in my test.

```
(defn bsearch
([data value f] (bsearch data value f 0 (count data)))
([data value f x y]
(let [idx (int (+ x (/ (- y x) 2)))
test (f (nth data idx) value)]
(cond
(zero? test) idx
(= x idx) nil
(pos? test) (recur data value f idx y)
(neg? test) (recur data value f x idx)))))

```
109. Clark

Here’s mine. I THINK it’s right, but hell if I know. No overflow bug. Using python.

# This MAY work in python 2.6, not sure. Tested on 3.1
########
# Binary searchy! Returns the index of the found element.
def bsearch(data, toFind):
begin = 0
end = len(data) – 1

while begin < (end – 1):
pivot = int(begin + (end – begin) / 2)

if data[pivot] == toFind:
return pivot
elif data[pivot] toFind:
end = pivot

if data[begin] == toFind:
return begin
elif data[end] == toFind:
return end

return -1

110. in C, it took me 1 hour with all the cosmetics (randomly initializing an array or user-provided size and sorting it…). I think the core function took me about 20 minutes. Damn, so much longer than I thought.

It seems to work at first glance. Here’s the core search function:

int binary_search(int *array, int begin, int end, int searchvalue)
{
int idx = 0;

if (end-begin == 0) return -1;
if (end-begin == 1) {
if (array[begin] == searchvalue) return begin;
else return -1;
}
idx = begin+(end-begin)/2;
if (array[idx] == searchvalue) return idx;

if (searchvalue < array[idx]) return binary_search(array, begin, idx, searchvalue);
else return binary_search(array, idx, end, searchvalue);

}

111. Jeff

First try failed when the target was outside the range of the array. Second try was successful.

112. Success!

```def search(array, term):
print "searching for %d in %s" % (term, array)
length = len(array)
if length == 1:
if array[0] == term:
print "Found %s in %s." % (term, array)
return True
else:
print "Did not find %s in %s." % (term, array)
return False
else:
mid = length/2
if array[mid] &lt;= term:
return search(array[mid:], term)
else:
return search(array[:mid], term)
```
113. Eh, screwed up my formatting. Here’s my successful binary search as a GitHub gist:

114. Anonymous

I wrote this recursive version:

```def index_of(elements, value):
if len(elements) == 0: return None
index = len(elements) / 2
if elements[index] == value: return index
if elements[index] > value: return index_of(elements[index + 1:], value)
return index_of(elements[:index], value)
```

It took about 10 minutes. I expected it to be correct. I then ran this test:

```def test(elements):
print("Not in list, below: " + str(index_of(elements, 0)))
print("Not in list, above: " + str(index_of(elements, 20)))
print("Finding all the elements in the list:")
for i in xrange(len(elements)):
print("Element %i (with value %i) was found at: %s" % \
(i, elements[i], index_of(elements, elements[i])))

list1 = [5, 6, 7, 8, 9]
list2 = [5, 7, 12, 15]

print("Test for uneven number of elements:")
test(list1)

print("Test for even number of elements:")
test(list2)
```

And got this result:

```Test for uneven number of elements:
Not in list, below: None
Not in list, above: None
Finding all the elements in the list:
Element 0 (with value 5) was found at: None
Element 1 (with value 6) was found at: None
Element 2 (with value 7) was found at: 2
Element 3 (with value 8) was found at: None
Element 4 (with value 9) was found at: None
Test for even number of elements:
Not in list, below: None
Not in list, above: None
Finding all the elements in the list:
Element 0 (with value 5) was found at: None
Element 1 (with value 7) was found at: None
Element 2 (with value 12) was found at: 2
Element 3 (with value 15) was found at: None
```

Wept a little, and corrected the 2 (two!) bugs, which were extremely obvious after the fact, namely that the greater-than should be less-than and that the index returned is wrong because I forgot to add the pivot when splitting. The end result is this:

```def index_of(elements, value, offset = 0):
if len(elements) == 0: return None
index = len(elements) / 2
if elements[index] == value: return index + offset
if elements[index] < value: return index_of(elements[index + 1:], value, index + 1 + offset)
return index_of(elements[:index], value, offset)
```
115. Sean O'Riordan

{-# LANGUAGE NoMonomorphismRestriction #-}
binsearch = ((head . filter ((1 ==) . length)) .) . iterate . listHalf
where
listHalf = join . (`ap` halfway) . dropTake
dropTake needle haystack = if ((haystack !! halfway haystack) <= needle) then drop else take
halfway = flip div 2 .length

116. Time to flex my ruby:

```class Array
def binary_search q
l, h= 0, self.length-1
until l > h
m = l + ((h - l) / 2)
v = self[m]
l = m+1 if q > v
h = m-1 if q < v
return m if q == v
end
nil
end
end

# TESTS
puts [1,4,394,590,1023,3924,50245].binary_search 394

data = *(1..500)
puts data.binary_search 25
puts data.binary_search 26
puts data.binary_search 27
puts data.binary_search 28
puts data.binary_search 29
puts data.binary_search 2300
puts data.binary_search 0
puts data.binary_search 500
puts data.binary_search 499

alpha = %W{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}
puts alpha.binary_search 'f'
puts alpha.binary_search 'b'
puts alpha.binary_search 'bob'

puts [1.3,1.4,1.5,1.6].binary_search 1.4
```

I hope the formatting didn’t fail. Wrote once, tested (worked) then reformatted into the above for fun.

117. Clark

It screwed with my formatting too. Here’s a fixed one:

http://gist.github.com/371583

118. Mike

Untested…..

```public class BinarySearch {
// Binary search for a target value in a given sorted array
// returns:
//    index of target value if found

public static int search(int[] array, int target) {
return search(array,target,0,array.length);
}

// search within range, inclusive of start index, exclusive of end index
public static int search(int[] array, int target, int start, int end) {
if (start>=end) return -1;

int middle=(start+end)/2;

int middleValue=array[middle];

if (target==middleValue) {
// we have found it!
return middle;
} else if (target<middleValue) {
// search bottom part
return search(array,target,start,middle);
} else {
// search top part
return search(array,target,middle+1,end);
}
}

public static void main(String[] args) {
if (search(new int[] {1,2,3,5},   3) != 2  ) throw new Error("Whoops!");
if (search(new int[] {1,2,3,5},   9) != -1 ) throw new Error("Whoops!");
if (search(new int[] {1,2,3,5}, -10) != -1 ) throw new Error("Whoops!");
if (search(new int[] {1,2,3,5}, 4  ) != -1 ) throw new Error("Whoops!");
if (search(new int[] {1,2,3,5}, 1  ) != 0  ) throw new Error("Whoops!");
if (search(new int[] {},        1  ) != -1 ) throw new Error("Whoops!");
}
}
```
119. Wrote this and thought through some test cases on paper. Took about 40 min, over which time I also pared it down from about 2x as long. Tested using arrays of 0,1,2,3 elements with search items hitting each as well as missing below and between each.
[pre]
def binarySearch(A, t):
a, b = 0, len(A)-1
while b >= a:
mp = a + (b-a)/2
if A[mp] == t:
return t
elif A[mp] < t:
a = mp+1
else:
b = mp-1
return None
[/pre]

120. A Johnson

Woohoo! I did it!

Of course, that assumes I implemented the testing algorithm correctly as well…

```public static void main(String[] args) {
for (int i = 0; i < 10000; i++){
int[] testArray = new int[(int) Math.random() * 10];
for (int k = 0; k < testArray.length; k++)
testArray[k] = (int) Math.random() * 10;
java.util.Arrays.sort(testArray);
int testSearch = (int) Math.random() * 100;
int result = bSearch (testArray, testSearch);
if (result == -1)
System.out.println (java.util.Arrays.binarySearch(testArray, testSearch) < 0);
else
System.out.println (java.util.Arrays.binarySearch(testArray, testSearch) == result);
}

}

public static int bSearch (int[] sortedArray, int value){
int minRange = 0, maxRange = sortedArray.length - 1;
while (maxRange - minRange > 0){
int index = minRange + (maxRange - minRange) / 2;
if (sortedArray[index] > value)
maxRange = index - 1;
else if (sortedArray[index] < value)
maxRange = index + 1;
else
return index;
}
return -1;
}
```
121. Max

I failed

122. Al

Below is the first version I came up with that I think will work. I’m going to try my luck and not test it :) I know this could be simplified further, but for science I’ll leave it like this.

```function binsearch(needle, arr) {
var start = 0;
var end = arr.length - 1;
do {
var midpoint = Math.floor((start + end) / 2);
if (arr[midpoint] == needle) {
return midpoint;
}
if (arr[midpoint] < needle) {
start = midpoint + 1;
} else {
end = midpoint - 1;
}
} while (start < end);
if (start == end && arr[start] == needle) {
return midpoint;
}
return -1;
}
```
123. dave-ilsw

# vim:tabstop=8:shiftwidth=4:smarttab:expandtab:softtabstop=4:autoindent:
# Python 2.5.4
# Non-obvious ends of blocks have been indicated with comments, in
# case the indents get lost when posting as a comment on the blog.
# This code has only been syntax checked.

class BinarySearch:
def __init__(self):
”’ Initialize ”’

def search(self, num, list):
list_length = len(list)
lower_bound = 0
upper_bound = list_length – 1
found_position = -1
done = False
while not done:
if upper_bound == lower_bound:
done = True
if num == list[upper_bound]:
found_position = upper_bound
#fi
else:
middle_point = lower_bound + int((upper_bound + 1 – lower_bound) / 2)
if num == list[middle_point]:
found_position = middle_point
done = True
elif num > list[middle_point]:
lower_bound = middle_point
if lower_bound lower_bound:
upper_bound -= 1
#fi
#fi
#fi
#elihw
return found_position
#fed

if __name__ == ‘__main__’:
bs = BinarySearch()
for list_length in range(1, 10):
list = range(0, list_length)
for num in list:
pass
#print num, list, bs.search(num, list)
#rof
#rof

124. pete gamache

Hell, if we’re posting without testing, I might as well go big.

```
INTEGER FUNCTION IBSRCH(ELT, ARR, IMIN, IMAX)
INTEGER ELT, IMIN, IMAX, ARR
DIMENSION ARR(IMIN:IMAX)
IBSRCH = -1
100   IMID = IMIN + (IMAX-IMIN)/2
IF (ELT-ARR(IMID)) 110, 120, 130
110   IF (IMID.EQ.IMAX) GOTO 199
IMAX = IMID
GOTO 100
120   IBSRCH = IMID
GOTO 199
130   IF (IMID.EQ.IMIN) GOTO 199
IMIN = IMID
GOTO 100
199   RETURN
END
```
125. zt
```def bsearch(value,array):
if array == []:
return False
first = 0
last = len(array)-1
middle = (last-first)/2
while first + 1 < last:
if array[middle] > value:
last = middle
else:
first = middle
middle = (last-first+1)/2+first
if array[middle] == value:
return True
return array[first] == value or array[last]==value
```

works (as far as i can tell with some quick testing)

126. Matthias Goergens

```module Main where
import Data.Sequence as Se
import Test.QuickCheck
import Data.Generics.Aliases (orElse)
import Data.Function

bin :: (Ord key) => key -> Se.Seq (key, item) -> Maybe item
bin key s | Se.null s = Nothing
| key < fst (Se.index s 0) || key > fst (Se.index s (l-1)) = Nothing
| l == 1 = Just . snd . Se.index s \$ 0
| otherwise = uncurry (on orElse (bin key)) \$ Se.splitAt (l `div` 2) s
where l = Se.length s
```
127. FlagCapper
```int bsearch(int array[], int T) {
int lowRange = 0, highRange = sizeof(array)/4;

while (42) {
int testID = (highRange - lowRange)/2;
int test = array[testID];
if (test == T)
return testID;
if (test < T)
lowRange = testID;
if (test > T)
highRange = testID;
}
return -1;
}
```
128. Rubberman

Next, describe an algorithm to implement an insertion sort where you insert data into the array, in the correct position so that the array doesn’t need to be sorted before use. Finally, alter that algorithm for dealing with inserting already sorted data into the array. As someone once said, been there, done that… :-)

In any case, these algorithms appear simple on the face of it, but implementing them correctly can take a considerable of time and doh!

BTW, you only mentioned not cheating by use of bsearch() – what about qsort()? :-)

129. Rubberman

Never mind! This a search, not a sorting problem… (Sound of Homer Simpson slapping his forhead) Doh!

130. Stephen Veit

Failed before testing:

def search(array, value, bottom = 0, top = nil)
top ||= (array.length – 1)

middle = (top + bottom) / 2
if array[middle] == value
return middle
elsif top == bottom
return nil
elsif value < array[middle]
return search(array, value, bottom, middle)
else
return search(array, value, middle, top)
end
end

After testing:

def search(array, value, bottom = 0, top = nil)
top ||= (array.length – 1)

middle = (top + bottom) / 2
if array[middle] == value
return middle
elsif top <= bottom
return nil
elsif value < array[middle]
return search(array, value, bottom, middle – 1)
else
return search(array, value, middle + 1, top)
end
end

131. Guy

Failed. Wrote a recursive implementation that returned the offset:

```def bsearch(a, k):
"""Return the position i in sorted a such that a[i] == k, or -1 if
no such i exists.  If a is not sorted, result is not defined"""
```

…but didn’t track the offset of splits, so it failed as soon as it recursed.

132. Justin

Seems to work correctly on the first try. Having looked through the comments, it appears my code is virtually identical to the stuff by Lawrence Kesteloot, except in a different language. Crazy.

```# Return index of value, nil if not found.
def bsearch(a, value)
low = 0
high = a.length - 1

while high &gt;= low
mid = low + ((high - low) / 2)
if a[mid]  value
high = mid - 1
else
return mid
end
end

return nil
end
```
133. Mike

So with no testing I was 95% there…i think.

But who writes anything without testing to find there errors? It’s an unreasonable expectation to be able to write anything more than the most trivial program without having errors prior to testing.

134. Here’s mine. I don’t know if this is good Lua style because I don’t know Lua very well.

It could be complained that perhaps the routine ought to return the index at which the value would need to be inserted, rather than nil, on not-found. I didn’t think of that until after I tested it.

```#!/usr/bin/lua
-- https://reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/

-- Apparently I am one of the 10%, because this code worked the first
-- time I tested it. It took me nine minutes to write and test.
-- function: 0x8865890
-- > print(bsearch({3, 5, 8, 11}, 8))
-- 3
-- > print(bsearch({3, 5, 8, 11}, 5))
-- 2
-- > print(bsearch({3, 5, 8, 11}, 3))
-- 1
-- > print(bsearch({3, 5, 8, 11}, 11))
-- 4
-- > print(bsearch({3, 5, 8, 11}, 12))
-- nil
-- > print(bsearch({3, 5, 8, 11}, 10))
-- nil
-- > print(bsearch({3, 5, 8, 11}, 1))
-- nil

-- I think this is a good task to use to teach thinking in terms of
-- formal logic.

-- find index of thing in sorted things in the range [first, last)
function bsearch_2(things, thing, first, last)
if first == last then return nil end
assert(last > first)

local midpoint = math.floor((first + last) / 2)
assert(midpoint >= first)
assert(midpoint < last)

local test = things[midpoint]
if test == thing then return midpoint end
if test > thing
then return bsearch_2(things, thing, first, midpoint)
else return bsearch_2(things, thing, midpoint+1, last)
end
end

function bsearch(things, thing)
return bsearch_2(things, thing, 1, #things+1)
end
```

It’s not my first time, but it’s been a few years.

After writing this I looked at some of the comments. One that I thought was particularly interesting was @Juanjo’s, which I think will infinite-loop if you look for, say, 3 in the one-element array [2]. Haven’t tested that, though.

135. Paul Hubbard

In python, as yet untested:
{source}

def bsearch(search_value, input_array):
“””
Assume array is sorted, min at [0] and max at [-1]
“””

# Ending conditions
if len(input_array) <= 0:
return False
if search_value input_array[-1]:
return False

split_index = int(math.floor(len(input_array) / 2))

if input_array[split_index] == search_value:
return True

if search_value > input_array[split_index]:
return bsearch(search_value, input_array[split_index+1:])
else:
return bsearch(search_value, input_array[0:split_index])
{/source}
Off to write unit tests and see….

136. ```Does the "pre" tag work in comments?
```
137. Paul Hubbard

Ooops… RTFM fail.

```
def bsearch(search_value, input_array):
"""
Assume array is sorted, min at [0] and max at [-1]
"""

# Ending conditions
if len(input_array) <= 0:
return False
if search_value < input_array[0]:
return False
if search_value > input_array[-1]:
return False

split_index = int(math.floor(len(input_array) / 2))

if input_array[split_index] == search_value:
return True

if search_value > input_array[split_index]:
return bsearch(search_value, input_array[split_index+1:])
else:
return bsearch(search_value, input_array[0:split_index])
```
138. Jon

Tried it in Python and failed because of a typo. Once I corrected the typo, the rest was correct.

139. seb

far from perfect. 15 minutes. doesn’t work when item is not in array (stack overflow)

```class Array
def bsearch(n, from = 0, to = self.length)
middle = from + ((to - from) / 2)
value = self[middle]

if value == n
return middle
elsif value < n
return bsearch(n, middle, to)
else
return bsearch(n, from, middle)
end
end
end

arr = [1,2,3,4,5,6,7,8,9,10]

arr.each do |search|
index = arr.bsearch(search)
puts "search(#{search}) => #{index}, #{arr[index]}"
end
```
140. Yup when in doubt I reach for my Perl hammer. It’s sad really. It’s worked for all the tests I’ve run but I’m sure I’m missing something.

```sub binsearch {
my \$target = shift;
my @range = @_;

my \$found = 0;
while ( @range ) {
my \$idx = floor( @range / 2 );
my \$mid = \$range[\$idx];
if ( \$mid == \$target ) {
\$found = 1;
last;
} elsif ( \$mid < \$target ) {
@range = @range[\$idx+1..\$#range];
} else {
@range = @range[0..\$idx-1];
}
}

return \$found;
}
```
141. Bevan

Ruby solution – Technically a fail due to if/else syntax error (ruby’s still a new language), but my algorithm implementation was sound…

Returns the array index of the element, if found, or -1 if not. (This seemed the only sensible return value to me… why return a number you already know?)

```def real_binary_sort(target,i_start,i_end,sorted_array)
@l = i_end - i_start
if (@l<0)
return "-1"
end
@index = i_start + (@l%2==0 ? @l/2 : (@l+1)/2)
if (target == sorted_array[@index])
return @index
elsif (target > sorted_array[@index])
return real_binary_sort(target,@index+1,i_end,sorted_array)
else
return real_binary_sort(target,i_start,@index-1,sorted_array)
end
end

def binary_sort(target,sorted_array)
rec_binary_sort(target,0,sorted_array.length-1,sorted_array)
end
```
142. Here’s my attempt in Clojure. I wrote it and subsequently tested it. I think it’s working. I may be wrong.

```(defn bsearch
([a e]
(bsearch a e 0 (dec (count a))))
([a e l h]
(if (not (< h l))
(let [m (floor (/ (+ l h) 2))
o (a m)]
(cond (> e o) (recur a e (inc m) h)
(< e o) (recur a e l (dec m))
(= e o) m)))))
```
143. Dan Lewis

Here’s a recursive pseudocode. Looks like I almost wrote in Python.

bsearch (T element, lst) returns index of element if in sorted list lst, otherwise throws. Assumes element has operator

if element is null: throw NullElement // assuming comparison operator can’t be defined for null
if lst is null: throw NullList
int len = sorted_list.length
if len == 0: throw EmptyList
int n = len / 2
T curr = sorted_list[n]
// need to bottom out!
if curr == element:
return n
else if len == 1:
throw ElementNotFound
else if len == 2 && curr < element:
throw ElementNotFound
else if curr element: // search down
return bsearch(element, lst[(0)..(n-1)])

144. Steve Witham: yes, the <pre> tag does sort of work in WordPress comments, but it won’t do all the things you’d want it to do; in particular, it throws away indentation, which is pretty critical in code samples (especially if you write Python). Instead, use {source}…{/source}, but use square brackets instead of curlies.

145. Nabeel Ali Memon

public static int binarySearch(int[] array, int begin, int end, int value) {
if (begin array.length – 1) throw new ArrayIndexOutOfBoundsException();
int high = end;
int low = begin;
int mid = low + ((high – low) / 2);

if (value == array[mid]) return mid;
if (value > array[mid]) return binarySearch(array, mid + 1, high, value);
if (value < array[mid]) return binarySearch(array, low, mid – 1, value);

return -1;
}

public static int binarySearch(int[] array, int value) {
return binarySearch(array, 0, array.length – 1, value);
}

146. Nope, I was wrong.

147. Yours truly

Here’s my first pass in ruby I think it works

```def bsearchexplicit(arr, firstindex, lastindex, n)
return (n == arr[firstindex]) || (n == arr[lastindex]) if (lastindex - firstindex < 2 )

middleindex = ((firstindex + lastindex)/2).floor
middlenum = arr[middleindex]

return true if (n == middlenum)
return bsearchexplicit(arr, firstindex, middleindex, n) if (n < middlenum)

return bsearchexplicit(arr, middleindex, lastindex, n)
end

def bsearch(arr, n)
return bsearchexplicit(arr, 0, arr.length - 1, n)
end
```
148. georges

I failed.
Wrote it in Ruby, ran it. Buggy.

Here’s the version I ended up getting working.
http://pastebin.com/rAwy1WcJ

149. dave-ilsw

Update after testing and seeing the blog update about source formatting.

```# vim:tabstop=8:shiftwidth=4:smarttab:expandtab:softtabstop=4:autoindent:
# Python 2.5.4
# Non-obvious ends of blocks have been indicated with comments, in
# case the indents get lost when posting as a comment on the blog.

class BinarySearch:
def __init__(self):
''' Initialize '''

def search(self, num, list):
list_length = len(list)
lower_bound = 0
upper_bound = list_length - 1
found_position = -1
done = False
while not done:
if upper_bound == lower_bound:
done = True
if num == list[upper_bound]:
found_position = upper_bound
#fi
else:
middle_point = lower_bound + int((upper_bound + 1 - lower_bound) / 2)
if num == list[middle_point]:
found_position = middle_point
done = True
elif num > list[middle_point]:
lower_bound = middle_point
if lower_bound < upper_bound:
lower_bound += 1
#fi
else:
upper_bound = middle_point
if upper_bound > lower_bound:
upper_bound -= 1
#fi
#fi
#fi
#elihw
return found_position
#fed

if __name__ == '__main__':
bs = BinarySearch()
for list_length in range(1, 10):
list = range(0, list_length)
for num in list:
print num, list, bs.search(num, list)
#rof
#rof
```
150. Dan Lewis

Argh, looks like my paste failed to get my search up case. Not sure why.

```bsearch (T element, lst) returns index of element if in sorted list lst, otherwise throws. Assumes element has operator

if element is null throw NullElement // assuming comparison operator can't be defined for null
if lst is null throw NullList
int len = sorted_list.length
if len == 0 throw EmptyList
int n = len / 2
T curr = sorted_list[n]
// need to bottom out!
if curr == element
return n
else if len == 1
throw ElementNotFound
else if len == 2 && curr < element
throw ElementNotFound
else if curr  element // search down
return bsearch(element, lst[(0)..(n-1)])
```
151. Nabeel Ali Memon

[Mike says: yes, Nabeel. You’d have thought I’d have linked to that article, wouldn’t you? Oh! Wait! …]

152. Doh! Of course I missed the point about returning the index of item in the array (which the description from the book doesn’t really point out). After a bit of thought here was my updated version to do that.

```sub binsearch {
my \$target = shift;
my @range = @_;

my \$found = -1;
my \$delta = 0;
while ( @range ) {
my \$idx = floor( @range / 2 );
my \$mid = \$range[\$idx];
if ( \$mid == \$target ) {
\$found = \$delta + \$idx;
last;
} elsif ( \$mid < \$target ) {
@range = @range[\$idx+1..\$#range];
\$delta += \$idx+1;
} else {
@range = @range[0..\$idx-1];
}
}

return \$found;
}
```
153. Dan Lewis

Third and final try, lt/gt seems to be the problem. Incidentally “preview comment” would have been nice.

```bsearch (T element, lst) returns index of element if in sorted list lst, otherwise throws. Assumes element has operator< == >

if element is null throw NullElement // assuming comparison operator can't be defined for null
if lst is null throw NullList
int len = sorted_list.length
if len == 0 throw EmptyList
int n = len / 2
T curr = sorted_list[n]
// need to bottom out!
if curr == element
return n
else if len == 1
throw ElementNotFound
else if len == 2 && curr < element
throw ElementNotFound
else if curr < element // search up
return n + bsearch(element, lst[(n+1)..(len-1)]) // works if lst[2..1] returns empty
else if curr > element // search down
return bsearch(element, lst[(0)..(n-1)])
```
154. N V

Yay, passed with this C:

```int *bsearch(int *base, int size, int key)
{
if(size <= 0 ) {
return 0;
}

int halfsize = size >> 1;
int pivot = base[halfsize];

if(pivot == key) {
return base + halfsize;
}

if(pivot < key) {
return bsearch(base + halfsize + 1, size - (halfsize + 1), key);
}

return bsearch(base, halfsize, key);
}
```
155. Iterative python, seems like a lot of people did the same. Once I remembered how the range of an array is specified, think it is OK. Caught the index out of bounds condition that others seemed to miss. Wouldn’t take a bet that something else is missing though!

def bshalf(array, N):
if len(array)==1:
if N==array[0]:
print ‘found’, N
return 1
else:
print ‘not in array, in bounds’
return 0
halflenarr=int(len(array)/2)
print halflenarr, len(array), array
if N>array[halflenarr]:
return bshalf(array[halflenarr+2: len(array)], N)
else:
return bshalf(array[0: halflenarr+2], N)

def bs(array, N):
lenarr=len(array)
if N>array[lenarr-1]:
print ‘outside initial array’
return 0
return bshalf(array, N)

156. foo

Javascript, iterative, seems to work.

```// returns index of value, or -1 if not found. array must contain sorted numbers.

function binSearch(array, value) {
var lo = 0;
var hi = array.length - 1;
var mid;

while(hi > lo) {
mid = Math.floor((hi + lo) / 2);

if(array[mid] < value) {
lo = mid + 1;
} else {
hi = mid;
}
}

return(array[lo] === value ? lo : -1);
}
```
157. Ryan

I did right before testing it, but it was a bit harder than I thought it should be and wasn’t the most elegant code.

158. ```#tail recursive binary search in python. Returns -1 or index of item in array
def bsearch(arr, value, lidx=None, hidx=None):
if arr is None:
return -1

if lidx==None:
lidx=0
hidx=len(arr)

#get the middle index and middle value in the section of the array
midx = (hidx+lidx)/2
midval = arr[midx]

# see if we found it
if midval  == value:
return midx

#if we didn't find it, and there is nothing else to search, return not found
elif hidx == lidx:
return -1

# if we found it and it is greater, look in the top half
elif value > midval:
return bsearch(arr,value,midx+1,hidx)

# value < midval, look in the bottom half
else :
return bsearch(arr,value,lidx,midx)

```

Forgot a “:” on else, otherwise right.

159. Peter

Cool Post!
Almost correct in python on first try…. It would return the correct index, and would handle out-of-bounds conditions, but with a search value in the range of but not in the list I hit a loop. I fixed it on the 2nd try. You can decide whether to count it as a success or fail.

160. Eddie Hedges

// c# implementation of binary search

public int BinarySearch( int[] array, int index)
{
int start = 0;
int end = array.Length;

while(start < end)
{
int mid = (start + end)/2;

if(index < array[mid])
{
end = mid;
}
else start = mid + 1;
}
return start;
// you could also return end because theoretically when the loop ends start and end will be the same spot in the arrray :)
}

161. Paul Hubbard

Code and unittests (all pass!) at http://pastebin.com/Rjr6wx1b

162. ruby-esque pseudocode, untested:

bsearch(arr,val){
if(arr.length==0)
return nil;
else if(arr.length==1 and val!=arr[0])
return nil;
n = (arr.length-1)/2
if(arr[n]==val)
return n
else if(arr[n]>val)
return bsearch(arr[0:n-1],val)
else
return bsearch(arr[n+1:arr.length-1],val)
}

163. William Laffin

Success!!! took me 40 minutes.

```def bsearch(list,elem,key=None):
if key is None:
key = lambda x:x
if len(list) &gt; 0:
return bsearchr(list,elem,0,len(list)-1,key)
return -1

def bsearchr(list, elem, i, j, key):
if (j - i) &lt; 2:
if key(list[i]) == elem:
return i
if key(list[j]) == elem:
return j
return -1
else:
mindex = (j - i)/2 + i
if key(list[mindex]) &lt; elem:
return bsearchr(list, elem, mindex, j, key)
else:
return bsearchr(list, elem, i, mindex, key)
```
164. Whipped this up in Obj-C. Haven’t even compiled it, much less tested it. But I believe it should work (shouldn’t even have the integer overflow bug documented in that link, and yes I wrote the code before following the link).

```@interface NSArray (BinarySearch)
- (NSUInteger)indexOfObjectUsingBinarySearch:(id)obj;
@end

@implementation NSArray (BinarySearch)
// performs a binary search in the array, returning the index of the found object or NSNotFound
// this assumes the array is in sorted order according to the compare: selector
- (NSUInteger)indexOfObjectUsingBinarySearch:(id)obj {
NSRange range = NSMakeRange(0, [self count]);
while (range.length > 0) {
NSUInteger pivotIdx = range.location + (range.length / 2); // center idx, rounded down
id pivot = [self objectAtIndex:pivotIdx];
switch ([obj compare:pivot]) {
case NSOrderedSame:
// we've found the object
return pivotIdx;
case NSOrderedAscending:
// object is in the lower half
range.length = pivotIdx - range.location;
break;
case NSOrderedDescending:
// object is in the upper half
range = NSMakeRange(pivotIdx+1, NSMaxRange(range) - (pivotIdx+1));
break;
}
}
return NSNotFound;
}
@end
```
165. dave-ilsw

Updated (and simpler) test section for my implementation, taking into account the need (mentioned in other comments) to test for numbers outside the range of values in the list and to test for numbers that are in the range, but not in the list:

```if __name__ == '__main__':
bs = BinarySearch()
list_length = 10
list = [1, 3, 5, 7, 9]
for num in range(0, 11):
print num, list, bs.search(num, list)
#rof
```
166. i posted my solution here: http://conigliaro.org/2010/04/19/am-i-one-of-the-10-of-programmers-who-can-write-a-binary-search/

be gentle. i haven’t been a full time programmer in quite a few years. ;-)

167. Rob Horvath

I gave this a go, and did some preliminary testing. It appears to function properly. Had to brush back up on my c skillz though.

```/*  This program will find the specified number in a pre-sorted array using
a binary search algorithm

command line: bsearch    ...  */

#define DEBUG	1

#include
#include

int main(int argc, char *argv[]) {

// Declare and Initialize our Variables
int search_value = 0;
int *sorted_array;
int range_lo = 0;
int range_hi = (argc - 3);
int array_center = 0;

// For returning info
int algo_iterations = 0;
int found_index = -1;

// Generic Counter
int i = 0;

// If we do not have at least three values passed, then the command line syntax is wrong
if (argc &lt; 3) {
printf(&quot;\nUsage:\nbsearch    ... \n\n");
return 0;
}

// Malloc memory for incoming array and make sure we were successful
sorted_array = (int*) malloc(sizeof(int) * (argc - 2));
if (sorted_array == NULL) {
printf("\nUnable to allocate memory for sorted array!\n\n");
return 1;
}

// Get our search value
search_value = atoi(argv[1]);

// Create our destination array
for (i = 0; i  1) {
array_center = ((range_hi - range_lo) / 2) + range_lo;
}
else if ((range_hi - range_lo) == 1) {
array_center = range_lo;
}

#ifdef DEBUG
printf("\n\nLoop #%d:\nrange_lo == %d\nrange_hi == %d\narray_center == %d\n\n", algo_iterations, range_lo, range_hi, array_center);
#endif

// Divide and Conquer our array

// See if we can short circuit
if (sorted_array[array_center] == search_value) {
found_index = array_center;
}
else if (sorted_array[array_center] &lt; search_value) {		// The search value falls in the top half
if ((range_hi - range_lo) == 1) {
range_lo = range_hi;
}
else {
range_lo = array_center;
}
}
else {
range_hi = array_center;
}
}

switch (found_index) {
case -1:
case -2:
free(sorted_array);
return 0;
break;
default:
printf(&quot;\n\nNeedle %d found at index position %d, using %d iterations.\n\n&quot;, search_value, found_index, algo_iterations);
free(sorted_array);
return 0;
break;
}
}

```
168. Rob Horvath

Sorry, let me try that again:

```/*  This program will find the specified number in a pre-sorted array using
a binary search algorithm

command line: bsearch <num_to_find> <array_index_0> <array_index_1> ... <array_index_n> */

#define DEBUG	1

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[]) {

// Declare and Initialize our Variables
int search_value = 0;
int *sorted_array;
int range_lo = 0;
int range_hi = (argc - 3);
int array_center = 0;

// For returning info
int algo_iterations = 0;
int found_index = -1;

// Generic Counter
int i = 0;

// If we do not have at least three values passed, then the command line syntax is wrong
if (argc < 3) {
printf("\nUsage:\nbsearch <num_to_find> <array_index_0> <array_index_1> ... <array_index_n>\n\n");
return 0;
}

// Malloc memory for incoming array and make sure we were successful
sorted_array = (int*) malloc(sizeof(int) * (argc - 2));
if (sorted_array == NULL) {
printf("\nUnable to allocate memory for sorted array!\n\n");
return 1;
}

// Get our search value
search_value = atoi(argv[1]);

// Create our destination array
for (i = 0; i < (argc - 2); i++) {
sorted_array[i] = atoi(argv[i + 2]);
}

// Iterate through our array until we find the result, or find nothing
while (found_index == -1) {
// Increment our iteration counter
algo_iterations++;

// Terminating condition
if (range_hi == range_lo) {
if (sorted_array[range_hi] == search_value) {
found_index = range_hi;
}
else {
}
}

// Find the center of our array
if ((range_hi - range_lo) > 1) {
array_center = ((range_hi - range_lo) / 2) + range_lo;
}
else if ((range_hi - range_lo) == 1) {
array_center = range_lo;
}

#ifdef DEBUG
printf("\n\nLoop #%d:\nrange_lo == %d\nrange_hi == %d\narray_center == %d\n\n", algo_iterations, range_lo, range_hi, array_center);
#endif

// Divide and Conquer our array

// See if we can short circuit
if (sorted_array[array_center] == search_value) {
found_index = array_center;
}
else if (sorted_array[array_center] < search_value) {		// The search value falls in the top half
if ((range_hi - range_lo) == 1) {
range_lo = range_hi;
}
else {
range_lo = array_center;
}
}
else {
range_hi = array_center;
}
}

switch (found_index) {
case -1:
case -2:
free(sorted_array);
return 0;
break;
default:
printf("\n\nNeedle %d found at index position %d, using %d iterations.\n\n", search_value, found_index, algo_iterations);
free(sorted_array);
return 0;
break;
}
}
```
169. Jeshua Smith

I was confident in my code until I was about to write the first testcase and realized that I’d forgotten to test for an array size of zero, but otherwise bugfree. Unlike most of the code posted here, I tested the target value against the first and last entry before doing a divide and conquer loop, since the definition states that the range being tested is the range in which the value must lie.

170. logophobia

it’s ruby, not tested. not elegant, but it “should” work.

```def bin_search_recur(arr, r_begin, r_end, to_find)
if(r_begin == r_end)
if(arr[r_begin] == to_find)
return r_begin
else
return -1
end
else
pivot = r_begin + (r_end - r_begin) / 2
if(arr[pivot] == to_find)
return pivot
elsif(arr[pivot] > to_find)
return bin_search_recur(arr, r_begin, pivot - 1, to_find)
else
return bin_search_recur(arr, pivot + 1, r_end, to_find)
end
end
end

def bin_search(arr, to_find)
return bin_search_recur(arr, 0, arr.size - 1, to_find)
end
```
171. Emo

Failed and took forever – now I hate my life — even more.

172. Here’s my go. Took me about 20 minutes. I guess I technically failed as it didn’t work on my first test, but it was really just a typo (I had first/last reverse on line 13). After fixing that, it seems to work fine:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 # Taking on the Binary Search challenge class Array # Binary search; assumes array is sorted # If value is found in the array, it returns an index where it can be found. # If the value occurs multiple times in the array, it will just return the # first place it is found (not necessarily the first occurrence in the array). # If the value is not found, it returns nil. def bsearch(value) return nil if self.length == 0 range = (0..self.length – 1) while range.last >= range.first mid = (range.last – range.first) / 2 + range.first case self.at(mid) <=> value when 0 # values are equal return mid when 1 # mid is greater range = (range.first..mid–1) when –1 # value is greater range = (mid+1..range.last) end end return nil end end

view raw

bsearch.rb

hosted with ❤ by GitHub

It would be helpful if you had a test set of searches that could be used to verify correctness.

173. Dietrich Epp

I know it’s right, I don’t *need* to test it.

```struct entry {
char *key;
char *value;
};

char *lookup(struct entry *table, size_t size, char const *key)
{
size_t l = 0, r = size, m;
int c;
while (l < r) {
m = (l + r) / 2;
c = strcmp(key, table[m].key);
if (c < 0)
r = m;
else if (c > 0)
l = m + 1;
else
return table[m].value;
}
return NULL;
}
```
174. dave-ilsw

Found a bug after adding the following two test conditions:

```    num = 5
list = []
print num, list, bs.search(num, list)
list = None
print num, list, bs.search(num, list)
```

Fails on an empty list:

```5 []
Traceback (most recent call last):
File "C:\svnwork\circulation\utility\binary-search.py", line 52, in <module>
print num, list, bs.search(num, list)
File "C:\svnwork\circulation\utility\binary-search.py", line 24, in search
if num == list[middle_point]:
IndexError: list index out of range
```

Commented out the first of the two new tests and the second new test also fails:

```5 None
Traceback (most recent call last):
File "C:\svnwork\circulation\utility\binary-search.py", line 54, in <module>
print num, list, bs.search(num, list)
File "C:\svnwork\circulation\utility\binary-search.py", line 11, in search
list_length = len(list)
TypeError: object of type 'NoneType' has no len()
```
175. Brian

Works for all my test cases.

Don’t flame me for using java.

```public static int Bsearch(int num, int[] array, int start, int end) {

int index = start + (end - start)/2;
if (num == array[index])
return index;

else {
if (start == end)
return -1;

if (num &gt; array[index])
return Bsearch(num, array, index+1, end);

else return Bsearch(num, array, start, index-1);
}
}

public static int Bsearch(int num, int[] array) {
return Bsearch(num, array, 0, array.length-1);
}
```
176. LOL @ Emo

… who I assume is joking …

:-)

Brad and others have expressed a wish that I’d provided a set of testcases. Unfortunately, to be useful such a set would need to be made available in a language usable by the code being tested, and as at least a dozen different languages have been used that’s not really feasible. Maybe I should have picked a lowest-common-denominator language like Java and mandated that … but I am glad I didn’t. It’s done my heart good to see the range of languages used here.

177. Annie

Untested

```#include <cstdlib>
// first: pointer to the first element
// last: pointer to one past the last element
// value: value to find
// returns NULL if not found, pointer to the element if found.
template <typename T>
T *bs(T *first, T *last, const T &value)
{
if (first == last) return NULL;
T *middle = (first+last)/2;
if (value < *middle) return bs(first, middle, value);
if (value > *middle) return bs(middle+1, last, value);
return value == *middle ? middle : NULL;
}
```
178. logophobia

I fail, after I submitted I realized I didnt account for the empty array case. The rest was correct

179. dave-ilsw

Added two lines to the top of the search method:

```    def search(self, num, list):
if not list:
return -1
```

All of my tests pass now.

180. Tested, but no corrections seemed necessary. Of course, I iterated through the three examples at the bottom of my code by hand. Not my prettiest code, but it handles the major cases. Took me about 35 minutes, including testing. The code was written in about 20 minutes with two bug fixes discovered during hand iteration (needed to add bot to mid if lowering the upper bound and mid to mid if raising the lower bound). I’ve not tried it with a larger data set.

```class Array
def bsearch(item)
bot = 0
top = self.size - 1
mid = (top - bot) / 2
idx = nil

while bot < top and idx.nil?
cur = self[mid]

if cur == item
idx = mid
break
end

if item < cur
top = mid - 1
mid = (top - bot) / 2 + bot
else
bot = mid + 1
mid = (top - bot) / 2 + mid
end

if mid > top
mid = top
elsif mid < bot
mid = bot
end
end

if bot == top and idx.nil? and self[bot] == item
idx = bot
end

idx
end

end

a = %w(1 2 3 4 6 7 8 10 11 12).map { |e| e.to_i }

puts "3 == a.bsearch(4)? [#{a.bsearch(4)}]"
puts "7 == a.bsearch(10)? [#{a.bsearch(10)}]"
puts "nil == a.bsearch(9)? [#{a.bsearch(9)}]"```
181. spoon16

C#

```        [TestMethod]
public void TestMethod1()
{
//build sample data
int[] array = new int[100];

for (int x = 0; x &lt; array.Length; x++)
array[x] = x * 2;

int find = 14;

//binary search
int currentIndex = array.Length / 2 - 1;
int upperIndex = array.Length - 1;
int lowerIndex = 0;

while (array[currentIndex] != find)
{
int index = currentIndex;

if (lowerIndex == index
|| upperIndex == index)
break;

if (array[index] &lt; find)
{
currentIndex = Convert.ToInt32(Math.Ceiling((upperIndex - index) / 2.0) + index);
lowerIndex = index;
}
else
{
currentIndex = Convert.ToInt32(Math.Floor((index - lowerIndex) / 2.0) + lowerIndex);
upperIndex = index;
}

Console.WriteLine(string.Format(&quot;[{0}]{1}&quot;, currentIndex, array[currentIndex]));
}

//result
if(array[currentIndex] == find)
Console.WriteLine(&quot;found&quot;);
else
}
```
182. spoon16

C#

```        [TestMethod]
public void TestMethod1()
{
//build sample data
int[] array = new int[100];

for (int x = 0; x < array.Length; x++)
array[x] = x * 2;

int find = 14;

//binary search
int currentIndex = array.Length / 2 - 1;
int upperIndex = array.Length - 1;
int lowerIndex = 0;

while (array[currentIndex] != find)
{
int index = currentIndex;

if (lowerIndex == index
|| upperIndex == index)
break;

if (array[index] < find)
{
currentIndex = Convert.ToInt32(Math.Ceiling((upperIndex - index) / 2.0) + index);
lowerIndex = index;
}
else
{
currentIndex = Convert.ToInt32(Math.Floor((index - lowerIndex) / 2.0) + lowerIndex);
upperIndex = index;
}

Console.WriteLine(string.Format("[{0}]{1}", currentIndex, array[currentIndex]));
}

//result
if(array[currentIndex] == find)
Console.WriteLine("found");
else
}
```
183. @Mike – you could just provide test cases in pseudocode and leave it up to us to convert it to our language.

184. untested and unrun. *fingers crossed*

```def binSearch(array, number):
"""recursive; returns the index in the original array which contains number"""
if len(array) == 0:

if len(array) == 1:
if array[0] == number:
return 0
else:

else:
mid = len(array) / 2
if array[mid] < number:
return binSearch(array[0:mid], number)
else:
return mid + binSearch(array[mid:], number)
```
185. Pavel Panchekha
```def bsearch(l, n, offset=0):
if not l:
raise ValueError
N = len(l)
pivot = N/2
if n < l[pivot]:
return bsearch(l[:pivot], n, offset)
elif n == l[pivot]:
return offset + pivot
else:
return bsearch(l[pivot+1:], n, offset + pivot + 1)
```

Success!

186. “Mike – you could just provide test cases in pseudocode and leave it up to us to convert it to our language.”

I guess. But in part, too, I deliberately held off because I know that some of the test cases will immediately show people aspects of the problem that I wanted to see whether they’d spot for themselves. One obvious example is the zero-length-array test case: as Kernighan Pike say, “Make sure your code “does nothing” gracefully”. And, sure enough, a few commenters have been brave and honest enough to admit that they overlooked that case.

There have been so many interesting comments here (and on Reddit and Hacker News) that I have lots of material for a followup article, probably to be posted tomorrow. That might include some abstract test-cases.

187. Ok so I did this one in ColdFusion and I was pretty lazy but used recursion. Since there is no “array split” type function in CF I also wrote one of those to make my life easier. I have not tested it; beyond making sure CF doesn’t find a syntax error

```<cffunction name="binarySearch" returntype="boolean" output="false">
<cfargument name="ary"	type="array"	required="true" />
<cfargument name="val"	type="string"	required="true" />

<cfset var l = structNew() />

<cfif ArrayLen(arguments.ary) GT 1>
<cfif ArrayLen(arguments.ary) EQ 2>
<cfreturn VAL((arguments.ary[1] EQ arguments.val OR arguments.ary[2] EQ arguments.val))>
<cfelse>
<cfset l.pos = Round(ArrayLen(arguments.ary)/2) />

<cfif arguments.ary[l.pos] EQ arguments.val >
<cfreturn 1 />
<cfelseif arguments.ary[l.pos] GT arguments.val>
<cfset arguments.ary = ArraySplit(arguments.ary, 1, l.pos-1) />
<cfelse>
<cfset arguments.ary = ArraySplit(arguments.ary, l.pos+1, ArrayLen(arguments.ary)) />
</cfif>

<cfreturn binarySearch(arguments.ary, arguments.val) />
</cfif>

<cfelse>
<cfif arguments.ary[1] EQ arguments.val>
<cfreturn 1 />
<cfelse>
<cfreturn 0/>
</cfif>
</cfif>

</cffunction>

<cffunction name="ArraySplit" returntype="array">
<cfargument name="ary"	type="array">
<cfargument name="sp"	type="numeric">
<cfargument name="ep"	type="numeric">

<cfset var l = structNew() />
<cfif arguments.ep LT arguments.sp>
<cfthrow message="End Point must be greater than or equal to the starting point" />
</cfif>
<cfif arguments.ep GT ArrayLen(arguments.ary)>\
<cfthrow message="End point can not be greater than the size of the array to split" />
</cfif>
<cfif arguments.sp GT arguments.sp>
<cfthrow message="Start Point must be less than or equal to the size of the array to split" />
</cfif>

<cfset l.a = ArrayNew(1) />
<cfloop from="#arguments.sp#" to="#arguments.ep#" index="l.i">
<cfset ArrayAppend(l.a, arguments.ary[l.i]) />
</cfloop>

<cfreturn l.a />

</cffunction>
```
188. Dachsbracke

Hi, did not read to the end and tested before posting. After posting I noticed the out of bound issues, guess that makes me part of the majority.

def binary_search(a, r, T):
while r != [] and r[0] != T:
print r
if T < mean(r):
r = [r[0], mean(r)]
else:
r = [mean(r), r[1]]
return r[0]

189. Paul Driver

This had a very silly off-by-one ((count v) instead of (dec (count v)) for the initial hi), so I failed. Seems to work now, though.

```(defn binary-search
([v x] (binary-search v x -))
([v x cmp]
(loop [lo 0 hi (dec (count v))]
(cond (> lo hi) nil
(= lo hi) (if (= 0 (cmp (v lo) x)) lo nil)
true      (let [mid (quot (+ lo hi) 2)
dif (cmp x (v mid))]
(cond (= dif 0) mid
(> dif 0) (recur (inc mid) hi)
(< dif 0) (recur lo mid)))))))
```
190. William Laffin

Success!!! took me 40 minutes. I didn’t want to cheat, so I read other comments after I made it, turns out you are supposed to use squares not curlies (whoops)

```def bsearch(list,elem,key=None):
if key is None:
key = lambda x:x
if len(list) > 0:
return bsearchr(list,elem,0,len(list)-1,key)
return -1

def bsearchr(list, elem, i, j, key):
if (j - i) < 2:
if key(list[i]) == elem:
return i
if key(list[j]) == elem:
return j
return -1
else:
mindex = (j - i)/2 + i
if key(list[mindex]) < elem:
return bsearchr(list, elem, mindex, j, key)
else:
return bsearchr(list, elem, i, mindex, key)
```
191. Zeca Urubu

My submission:

```
#return pos in case of sucess, -1 if didn't find it

def bsearch(sortedList, n):
pos = 0
size = len(sortedList)

if(size == 0):
return -1

if(size == 1):
if(sortedList[pos] != n):
return -1
else:
return pos

pos = size / 2

if(sortedList[pos] == n):
return pos
else:
r1 = bsearch(sortedList[:pos],n)
r2 = bsearch(sortedList[pos:],n)
if(r1 != -1):
r1 = r1 + 0
return r1
elif r2 != -1:
r2 = r2 + pos
return r2
else:
return -1
```
192. James Birchall

Seems to work…though it’ll report incorrectly if end < start. I thought about that condition after I ran the test (but without checking for the case or failing the test) so I'm not sure if that counts as a failure or not…given the way the code works, it should be an impossible input anyways but I figured it should be complete in isolation, without relying on the usage in main to be right (can't do much about whether the array is ordered or the len is specified correctly though…gotta love pointers, eh?).

```// Assumes list is ordered.
int bs(unsigned int len, int list[], int val, unsigned int start, unsigned int end){
// Preconditions
if (end > len - 1) return -1;
if (start < 0) return -2;
if (end - start < 0) return -3;

// Boundary checking short-circuit.
// Saves function calls if the value isn't in the list at the expense
// of slightly greater constant cost.
if (list[start] > val) return -4;
if (list[end] < val) return -5;

unsigned int pos = start + ((end - start) >> 1);
int pos_val = list[pos];

if (pos_val == val) return pos;
else if (pos_val < val) return bs(len, list, val, pos + 1, end);
else return bs(len, list, val, start, pos - 1);
}

```
193. I see I also forgot to test the empty array case. So line 25 changes to

```		<cfif ArrayLen(arguments.ary) AND (arguments.ary[1] EQ arguments.val)>
```
194. I *think* mine is correct.

Did it in about 20 minutes in haXe, followed all your rules to the letter.

```static function binarySearch(array:Array<Float>, neededValue:Float)
{
var lo:Int = 0;
var hi:Int = array.length;

if (hi == 0)
return -1;

while ((hi - lo) >= 2)
{
var mid:Int = Math.floor((lo + hi)/2);
var foundValue:Float = array[mid];
if (foundValue == neededValue)
return mid;
else if (foundValue < neededValue)
lo = mid;
else
hi = mid;
}

if (array[lo] == neededValue)
return lo;
else
return -1;
}
```
196. Jason

Success, I think. SBCL’s compiler found a typo bug for me, but it worked the first time I tested it. I haven’t heavily tested it though. For large arrays (log(n) bigger than stack), an optimize declaration is required on bsearch to get most lisps to perform a TCO. I was aware of this before testing, and have only omitted it to make the code look cleaner.

The 90% error rate doesn’t surprise me at all. Where I work, we have a rule of thumb: “If it hasn’t been tested, it doesn’t work” It is right a lot more than 90% of the time.

If I got this right, it’s only because I’ve done it so many times before.

```(defun middle (a b)
(truncate (/ (+ a b) 2)))

(defun bsearch (a search start end)
(let ((pivot (middle start end)))
(cond
((= (aref a pivot) search) pivot)
((= start end) nil)
((< (aref a pivot) search)
(bsearch a search (+ 1 pivot) end))
(t (bsearch a search start pivot)))))
```
197. Zeca Urubu

Ops, I forgot to write the number of tries:

4 tries / 20 minutes

198. Tim Kostka

untested:

have array x() with elements
function to return index i of array x() which matches x(i) = y, else return -1
zero based array
x() is sorted such that x(i) <= x(i+1) for valid indices i, i+1

function find(y)
n = x.length();
min = 0;
max = n – 1;
do while (min < max)
test = (min + max) / 2
if x(test) y then
max = test – 1
else
return test
end if
loop
return -1
end function

199. Dachsbracke

And another version in whitespace that worked right from the scratch:

200. PS: time to complete was 18 minutes, 21 seconds according to git.

201. Tada! My first ever python code. I tested it with 20000 randomly generated arrays, but I’m still not confident.

```def binaryS(array, sought, lower, upper):
guess = lower + int(math.floor(upper-lower)) / 2
if array[guess] == sought:
return guess
elif upper-lower >= 1:
if array[guess] < sought:
return binaryS(array, sought, guess+1, upper)
elif array[guess] > sought:
return binaryS(array, sought, lower, guess-1)
else:
return -1

```
202. Annie

Code at (Annie // April 19, 2010 at 9:39 pm) doesn’t compile,
the line
T *middle = (first+last)/2;
should be
T *middle = first + (last-first)/2;

203. ```# Mon Apr 19 14:51:14 PDT 2010 - started exercise
# Mon Apr 19 14:58:12 PDT 2010 - submitting implementation pre-test,

def bsearch(needle, haystack):
remain = len(haystack)
offset = 0

while remain > 0:
i = offset + (remain / 2)

if haystack[i] == needle:
return i
else:
if haystack[i] < needle:
offset = i
remain -= ((remain / 2) or 1)

```
204. 18 min in C++. Works with STL random iterators and with any type T which is LessThanComparable.

205. mjk

Mine works according to the included test. Very nearly messed up the midpoint calculation but caught it at the last minute before I ran the test.

def binary_search(a,target):
def search_range(begin,end):
if end-begin == 0:
return -1
if end-begin == 1:
if a[begin] == target:
return begin
else:
return -1
middle = (end+begin)/2
if target < a[middle]:
return search_range(begin,middle)
else:
return search_range(middle,end)

return search_range(0,len(a))

def test_search(a,target):
ix = binary_search(a,target)
if target in a:
assert ix == a.index(target), "failed for target == %d" % target
print target, ix
else:
assert ix == -1, "failed for target == %d" %target
print target, ix

a = range(0,100,3)
for t in range(-2,105):
test_search(a,t)

206. (self smack for not reading markup instructions properly, this is my second attempt at posting)

I prioritized legibility, went with recursion, had one bug that I fixed (I wasn’t checking array max index). Nice idea.

```#!/usr/bin/env ruby

@elements_checked = []

def seek_element( search_value, index_to_check, minimum_to_check, maximum_to_check, array )
@elements_checked << index_to_check

if array[index_to_check] == search_value
return index_to_check
end

if search_value < array[index_to_check]
next_index_to_check = (minimum_to_check + index_to_check) / 2
maximum_to_check = index_to_check
else
next_index_to_check = (maximum_to_check + index_to_check) / 2
minimum_to_check = index_to_check
end

if next_index_to_check == index_to_check
if next_index_to_check == array.size - 2
next_index_to_check = array.size - 1
else
return nil
end
end

seek_element( search_value, next_index_to_check, minimum_to_check, maximum_to_check, array )
end

array_size = ARGV[0].to_i
random_range = ARGV[1].to_i
search_value = ARGV[2].to_i

puts "looking for #{search_value} amidst #{array_size} elements ranging from 0 to #{random_range - 1}"

if random_range <= search_value
puts "random_range needs to be greater than search_value"
exit 0
end

sorted_array = (0..array_size).collect {|i| rand(random_range)}.sort

first_index_to_check = sorted_array.size / 2
first_minimum_to_check = 0
first_maximum_to_check = sorted_array.size - 1

index_with_value = seek_element( search_value, first_index_to_check, first_minimum_to_check, first_maximum_to_check, sorted_array )

puts "Did #{@elements_checked.size } searches: #{@elements_checked.inspect}."
if index_with_value
sorted_array[index_with_value] = "**#{ sorted_array[index_with_value] }**"
puts "Found on #{index_with_value}"
else
puts "Not present"
end
puts sorted_array.inspect
```
207. John Dawson
```def bsearch(lst, x, lo=None, hi=None):
if lo is None:
lo = 0
hi = len(lst)-1

if lo < hi:
return None

mid = (lo+hi)/2
if x == lst[mid]:
return mid
elif x < lst[mid]:
return bsearch(lst, x, lo, mid-1)
else:
return bsearch(lst, x, mid+1, hi)
```

It did work the first time I ran it, much to my delight. However, I'm pretty sure that without the problem setup, designed to induce extreme paranoia, I would have failed. It's easy to see why 90% of the people in Bentley's test would have failed.

208. Tom
```def bsearch(arr, find):
low = 0
high = len(arr)

while True:
if high == low and arr[high] != find:
return -1

index = (high - low)/2 + low
if arr[index] == find:
return index
elif arr[index] > find:
high = index
else:
low = index
```

Yeah, infinite loop in some cases when the result’s not found. Three-second fix, but we’re going for first try, huh.

```def bsearch(arr, find):
low = 0
high = len(arr)

while True:
index = (high - low)/2 + low
if arr[index] == find:
return index
elif index == low:
return -1
elif arr[index] > find:
high = index
else:
low = index
```
209. Erik Karulf

I had an off-by-one error when initializing the upper bound, outside of that it was a success.

210. I like the challenge, but what kind of a lunatic would write code before writing tests?

211. Mark Cogan

Haven’t tested it at all. Think I have all the edge cases. Needs golfing.

```# searches a sorted array for a target
# assume array is sorted, contains numbers, and \$target is also a number

sub bsearch (@\$) {
my (@array, \$target) = @_;

# sanity check for empty arrays
unless (scalar @array) {
return undef;
}

my \$low = 0;
my \$high = \$#array; # always >= 0

# sanity check if \$target is out of bounds
if (\$target < \$array[\$low] ||
\$target > \$array[\$high]) {
return undef;
}

# we are guaranteed that \$low <= \$high
return _bsearch(\@array,\$low,\$high,\$target);
}

sub _bsearch {
my (\$array, \$low, \$high, \$target) = @_;

my \$mid = \$low + int((\$high - \$low)/2); # assuming \$low < \$high, then \$low <= \$mid <= \$high

# is the midpoint the number we're looking for? Then we're done.
if (\$ar->[\$mid] == \$target) {
return 1;
}
# were we searching over an range of a single index? Then we're done.
elsif (\$high == \$low) {
return undef;
}
# is the midpoint higher than the target?
# Then we search between the low end and the midpoint.
# If \$low == \$mid, then \$high == \$low +1, so the next pass
# will be over a single index and will be caught by the previous clauses
elsif (\$ar->[\$mid] > \$target) {
return _bsearch(\$array, \$low, \$mid, \$target);
}

# we know \$ar->[\$mid] < \$target
# if \$low == \$mid, then \$high = \$low+1, so we can explicitly
# test \$ar->[\$high] as the remaining possible location of \$target
elsif (\$mid == \$low) {
return \$ar->[\$high] == \$target;
}
# otherwise the midpoint was below the target and \$mid > \$low, so \$high > \$mid
else {
return _bsearch(\$array, \$mid, \$high, \$target);
}
}
```
212. bah, close. i put ” on line 14. once i fixed that, everything else seems to work fine.

213. Daniel
```def binary_search(seq, elem):
if seq is None or len(seq) == 0:
return -1
lower, upper = 0, len(seq) - 1

while lower < upper and lower >= 0:
index = upper / 2
compare = cmp(elem, seq[index])
if compare < 0:
lower, upper = lower, index - 1
elif compare > 0:
lower, upper = index + 1, upper
else:
return index
if seq[lower] == elem:
return lower
else:
return -1```

This was my untested code.

I got the calculation of index wrong, it should be index = lower + (upper – lower) / 2

214. wow, wordpress is a terrible medium for this exercise. this should really be on a forum where it’s possible to have threaded comments, because the comment section here has become a complete clusterf*ck.

215. Troy

Simple recursive Python version. Seems to work fine:

```def bs(array, value, first, last):
print(array[first:last])
if first == last and array[first] != value:
return False
else:
middle = first + int((last - first)/2)
if array[middle] == value:
return middle
elif array[middle] > value:
return bs(array, value, first, middle)
elif array[middle] < value:
return bs(array, value, middle, last)
```
216. This was my javascript effort, seems to work okay:

```function binarySearch(array, T) {
if (array.length === 0)

var index = array.length / 2;
if (array.length % 2 === 1)
index -= .5;

if (array[index] < T)
return index + 1 + binarySearch(array.slice(index + 1), T);

if (array[index] > T)
return binarySearch(array.slice(0, index), T);

return index;
}
```
217. Mikle

I wont post the code because you have 100s of examples, but for the sake of your “poll” – I did it in Python, coded it, reviewed it and than ran it without a single bug (Well I did slack off on writing meaningful exception messages :)

I hope to see the results soon, although I fear that they will be badly skewed.

218. Andres F.

Failed really stupidily by returning the relative index (from the evaluated range) instead of the absolute index.

Changed the code, ran the tests again and everything worked correctly. Woe is me.

Used ruby, btw.

219. Fun stuff :D

phps, untested.

```    function BinarySearch(\$pSortedArray, \$pTarget)
{
\$oIndex = 0;
\$oRangeFrom = 0;
\$oRangeTo = count(\$pSortedArray) - 1;
while(\$oRangeFrom <= \$oRangeTo)
{
\$oIndex = floor( (\$oRangeFrom + \$oRangeTo ) /2 );

if(\$pTarget > \$pSortedArray[\$oIndex])
{
\$oRangeFrom = \$oIndex + 1;
}
else if(\$pTarget < \$pSortedArray[\$oIndex])
{
\$oRangeTo = \$oIndex - 1;
}
else
{
return(\$oIndex);
}
}

return( -1 );
}

```
220. Geoff K

Wrote this in Ruby in about an hour. Since I couldn’t test before hand I made that final “if” block instead of actually figuring out what’s going on.

It passes the tests that I came up with.

```def bin_search(arr,val)
start_index = 0
end_index = arr.length - 1
mid_index = ((end_index - start_index) / 2) + start_index

while mid_index != start_index do
if arr[mid_index] > val
end_index = mid_index
elsif arr[mid_index] <= val
start_index = mid_index
end
mid_index = ((end_index - start_index) / 2) + start_index
end

if arr[start_index] == val
return start_index
elsif arr[end_index] == val
return end_index
else
return nil
end
end

```
221. def bsearch(item, l, offset=0):
if len(l) > 1:
idx = len(l)/2
p = l[idx]
if p == item:
return idx + offset
elif p item:
return bsearch(item, l[:idx], offset)
else:
if l[0] == item:
return offset
return None

222. python:

```def find(v,T):
"v is sorted; return i so that v[i]=T, or None if no such i exists"
a=0
b=len(v)
# i in [a,b) if v[i]=T
while a<b:
m=a+(b-a)/2
p=v[m]
if p==T: return m
if T<p:  b=m
else:    a=m+1
return None
```

I’m 99.5% sure there’s no bug in the above. I was aware already of the integer overflow complaint, which is the only reason I didn’t use (a+b)/2.

A more interesting task would be to return the largest range [a,b) such that v[i]=T for a<=i<b

223. Dan Lidral-Porter

First Erlang implementation, it seems.

```-module(bsearch).
-export([bsearch/2, random_sorted_list/1]).

bsearch(List, N) ->
io:format("searching ~w for ~w~n", [List, N]),
bs_rec(List, N, 1,length(List)).

bs_rec(List, Goal, Start, Stop) ->
Mean = erlang:trunc((Start + Stop) / 2),
Nth = lists:nth(Mean, List),

if
Start == Stop ->
if
Nth == Goal ->
{Goal, Mean};

true ->
not_found
end;

Nth < Goal ->
bs_rec(List, Goal, Mean + 1, Stop);

Nth == Goal ->
{Goal, Mean};

Nth > Goal ->
bs_rec(List, Goal, Start, Mean-1)
end.
```

When I was scrolling down to post, I saw a comment that reminded me that I forgot about the 0-length case. Darn.

If I add a guard in bsearch() to return the not_found atom if the length of the list is 0, then I think I passed. At least, I’ve tried all the cases I can think of and it works fine.

224. Ok, here’s mine. 25min and completely untested, thus probably horribly wrong and/or buggy (I usually copy/paste even my email address because I tend to mistype it…):

```#!/usr/bin/ruby

\$nComp = 0

def binSearch(array, el, mi, ma)
\$nComp += 1

# out of range - error
if el < array[mi] || el > array[ma]
return nil
end

# found it!
if el == array[mi]
return mi
end
if el == array[ma]
return ma
end

if mi >= ma-1
return nil
end

half = (mi + ma)/2

if el < array[half+1]
binSearch(mi+1, half)
else
binSearch(half+1, ma-1)
end
end

nElements = ARGV[0].to_i

arr = []

nElements.time do
arr << rand(100)
end

arr.sort!

puts "array:"
puts arr.join(" ")

elem = 0

puts "enter element to search for: "
\$stdin >> elem

puts "looking for " + elem.to_s

ret = binSearch(arr, elem, 0, arr.length-1)

puts \$nComp.to_s + " comparisons"

if ret == nil
else
puts "element " + elem.to_s + " found at " + ret.to_s + "!"
end
```
225. kwantam

Did it in Haskell in 5 minutes, stupidly left out one base case and found it with the second test case. I admire Matthias Goergens’s solution for being a bit more Haskell-ey than mine.

226. Will

Try again, with square brackets this time.

In Python (2.6 flavor). Untested.

```def binary_search(sequence, target):
"""Return the index in the sorted sequence of target or None if target
is not in sequence."""

start_i = 0
end_i = len(target)

while True:
if end_i <= start_i:
return None

length = end_i - start_i

midpoint_i = start_i + length / 2

midpoint = sequence[midpoint_i]

if midpoint == target:
return midpoint_i

if midpoint > target:
end_i = midpoint_i
else:
start_i = midpoint_i + 1
```
227. Joshua Leners

I failed.

228. samuel

Tested, no bugs found… yehaa :)

```int binary_search(vector<int>& arr, int needle)
{
/// range is at the beginning = entire array
int lower = 0;
int upper = arr.size()-1;
int middle = 0; // will be set in loop

/// if lower == upper the range is 1
while(lower < upper)
{
// find the middle
middle = floor((upper-lower)/2.0) + lower;

if(arr[middle] == needle)
return middle; // yay, found it!

if(arr[middle] > needle)
// middle is to big => kill upper half
// middle itself is also out of range => -1
upper = middle-1;
else // middle is to small => kill lower half
lower = middle+1;
};
if(lower == upper // just to make sure, array wasn't empty
and arr[lower] == needle)
return lower; // gotcha!

return 0;
}
```

Well, it looks like, there will be much too much code to review ;)
It certainly was interesting. It certainly looks easy but there are some pitfalls.

229. Chris

I failed my first run because of two typos which resulted in a logic error, so I added a case tester to debug and correct. Seems to work for all the cases I could think of.

```sub b_search(\$\$;\$\$) {
my( \$ary, \$search, \$x, \$y ) = @_;
# helper
if ( !defined( \$x ) || !defined( \$y ) ) {
return b_search(\$ary, \$search, 0, \$#{\$ary} );
}
if  ( \$x == \$y ) {
return \$x if ( \$ary->[\$x] eq \$search );
return -2;
} elsif ( \$x > \$y ) {
return -3;
}
my \$mid = int((\$y-\$x)/2) + \$x;
return \$mid if \$ary->[\$mid] eq \$search;
if ( \$search lt \$ary->[\$mid] ) {
return b_search( \$ary, \$search, \$x, \$mid - 1 );
} else {
return b_search( \$ary, \$search, \$mid + 1, \$y );
}
return -1;
}
```
230. Todd Moon

What constitutes testing? Just running the code? What about using pencil and paper to help you test it by eye? I wrote the whole thing, but found one obvious bug really quickly just by looking at it. Then I did some testing with an example array and used paper to help track values and found another bug.

I wrote up unit tests in the code then ran it. Output: “Done. Press any key.” Total time = 1 hour. Language = C#.

It may not be as elegant as other posted algorithms. Rather than just checking the midpoint, it also checks the start and end at the same time. It might make more comparisons than is necessary in some cases, but it also makes far fewer comparisons in other cases (where the value you want is in a very early or late position of a large array.) It’s probably a wash. It at least never compares the same position more than once.

```class Program
{
static void Main( string[] args )
{
int[] values1 = new int[] { };
int[] values2 = new int[] { 2 };
int[] values3 = new int[] { 2, 3 };
int[] values4 = new int[] { 2, 3, 5, 7 };
int[] values5 = new int[] { 2, 3, 5, 7, 11 };
int[] values6 = new int[] { 2, 3, 5, 7, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 };

TestBinarySearch( values1, 7, -1 );
TestBinarySearch( values1, 0, -1 );

TestBinarySearch( values2, 2, 0 );
TestBinarySearch( values2, 1, -1 );
TestBinarySearch( values2, 3, -1 );

TestBinarySearch( values3, 1, -1 );
TestBinarySearch( values3, 4, -1 );
TestBinarySearch( values3, 2, 0 );
TestBinarySearch( values3, 3, 1 );

TestBinarySearch( values4, 1, -1 );
TestBinarySearch( values4, 3, 1 );
TestBinarySearch( values4, 5, 2 );
TestBinarySearch( values4, 7, 3 );
TestBinarySearch( values4, 8, -1 );

TestBinarySearch( values5, 1, -1 );
TestBinarySearch( values5, 15, -1 );
TestBinarySearch( values5, 5, 2 );
TestBinarySearch( values5, 11, 4 );

TestBinarySearch( values6, 1, -1 );
TestBinarySearch( values6, 103, -1 );
TestBinarySearch( values6, 5, 2 );
TestBinarySearch( values6, 53, 14 );
TestBinarySearch( values6, 17, 5 );

Console.WriteLine( "Done. Press any key." );
}

static int testNumber = 0;

private static void TestBinarySearch( int[] values, int target, int expectedResult )
{
testNumber++;

int position = BinarySearch( values, target );

if ( position != expectedResult )
{
Console.WriteLine( String.Format( "Unexpected result in test {0}. Expected: {1}. Received: {2}.", testNumber, expectedResult, position ) );
}
}

private static int BinarySearch( int[] values, int target )
{
if ( values.Length == 0 )
{
return -1;
}

return BinarySearch( values, target, 0, values.Length - 1 );
}

private static int BinarySearch( int[] values, int target, int iStart, int iEnd )
{
if ( values[ iStart ] == target )
{
return iStart;
}
else if( values[ iEnd ] == target )
{
return iEnd;
}
else if ( values[ iEnd ] < target || values[iStart] > target )
{
return -1;
}

int iMid = ( ( iEnd - iStart + 1 ) / 2 ) + iStart;

if ( values[ iMid ] == target )
{
return iMid;
}
else if ( values[ iMid ] < target )
{
return BinarySearch( values, target, iMid + 1, iEnd - 1 );
}
else
{
return BinarySearch( values, target, iStart + 1, iMid - 1 );
}
}
}```
231. I tested it against one array quickly…and it failed. Had two bugs, both 1 character long. First I initially passed the array by reference (so an extra &) in order not to have to copy the array, but I guess you can’t do that in PHP. Second, I accidentally substracted the end and starts to get the average instead of dividing.

Took me ~15 minutes. Sloppy code and not sure if it actually works.

Cool experiment.

```<?php
function binary_search(\$sorted_array, \$T)
{
\$start = 0;
\$end = count(\$sorted_array) - 1;
while (\$end - \$start > 0)
{
if (\$end - \$start == 1)
{
if (\$sorted_array[\$end] == \$T)
{
return \$end;
}
elseif (\$sorted_array[\$start] == \$T)
{
return \$start;
}
return -1;
}
\$halfway = ceil((\$end + \$start)/2.0);
if (\$T == \$sorted_array[\$halfway])
{
return \$halfway;
}
elseif (\$T > \$sorted_array[\$halfway])
{
\$start = \$halfway;
}
else
{
\$end = \$halfway;
}
}
return (\$sorted_array[0] == \$T ? 0 : -1);
}
```
232. Well… Test results: 1 type, 1 Ruby fail (who ever uses input from the terminal ever…), 1 forgotten args in the recursion (D’OH!). But the algorithm works quite fine (although I do *not* check the 0-array case).

```# Return undef if \$T not found in @\$list.
# Otherwise, return index of position of \$T in @\$list.
# If \$T appears more than once, any valid index may be returned.
# @\$list must be pre-sorted.

sub binary_search {
my ( \$T, \$list ) = @_;

# Invalid arguments, empty list
return unless defined \$T
&& defined \$list
&& ref \$list eq 'ARRAY'
&& @\$list > 0;

# \$pos is midpoint, more or less. Err on the low side.
my \$pos = int( scalar(@\$list) / 2);

# Comparison; assume strings
# \$cmp < 0 if \$T lt \$list->[\$pos]
# \$cmp == 0 if \$T eq \$list->[\$pos]
# \$cmp > 0 if \$T gt \$list->[\$pos]
my \$cmp = \$T cmp \$list->[\$pos];

# Good guess
return \$pos if \$cmp == 0;

if ( \$cmp < 0 ) {
return if \$pos == 0;    # no elements on left
my @new_list = splice( @\$list, 0, \$pos-1 );
return binary_search( \$T, \@new_list );
}
else {
return if \$pos+1 == scalar(@\$list);     # no elements on right
my @new_list = splice( @\$list, \$pos+1 );
my \$new_pos = binary_search( \$T, \@new_list );
# If \$new_pos is undef, \$T wasn't found on the right.
# Otherwise, \$new_pos is the position in @new_list, which is offset
# from the position in \$list by \$pos+1 because of the splice arguments.
if ( defined \$new_pos ) {
return \$new_pos + \$pos + 1;
}
else {
return;
}
}
}
```
234. shezi

I got it right on the first try. Yay for the 10%.

Note that your results will skew for success anyway, for several reasons. One is that people who read programming blogs are skewing for the better end, but the more important thing is that some unsuccessful people will not post, no matter what you told them.

```import random
arr = range(1000)
x = random.randrange(1000)

def binsearch(arr, x):
print "searching for %d" % x
def binsearch_aux(arr, x, min, max):
print "  is between %d and %d" % (min, max)
if arr[min] == x:
print "  found at %d" % min
return min
middle = (min + max) / 2
pivot = arr[middle]
if pivot <= x:
return binsearch_aux(arr, x, middle, max)
else:
return binsearch_aux(arr, x, min, middle)

if arr[0] < x > arr[-1]:
print "  element is not in array"
return None

return binsearch_aux(arr, x, 0, 1000)

# test cases
binsearch(arr, 500)
binsearch(arr, 501)
binsearch(arr, 502)
binsearch(arr, 499)
binsearch(arr, 1)
binsearch(arr, 0)
binsearch(arr, 999)
binsearch(arr, x)
binsearch(arr, 1000)

arr = list()
for i in range(1000):
arr.append(random.randrange(100000000))
arr.sort()
print "starting random test"
for x in range(1000):
if binsearch(arr, arr[x]) != x:
print "MISSING AT %d" % x
print arr
import sys
sys.exit(-1)

```
235. Fencepost error, used “pivot = min” instead of “pivot = min + 1”. Infinite loop if no match. Worked when I fixed it, no boundary errors, remembered to check for an empty array.

236. Dan Lidral-Porter

My implementation also fails on duplicate keys. Oops.

237. paulb
```example1 = ['a', 'b', 'c', 'd', 'e', 'f']
example2 = ['a', 'c', 'd', 'e', 'f']
example3 = ['b', 'f', 'f', 'f', 'f', 'f']

def binsearch(arr, findval):

while 1:
mid = len(arr)/2
if len(arr) == 0: return -1
if len(arr) == 1 and arr[0] != findval: return -1

if arr[mid] > findval :
#LHS
arr = arr[:mid]
elif arr[mid] < findval :
#RHS
arr = arr[mid:]
elif arr[mid] == findval:
return arr[mid]

print binsearch(example1, 'b')
print binsearch(example2, 'b')
print binsearch(example3, 'z')
```

1. I put in a couple of tentative tests at entry the second is probaby not needed
2. I totally failed to return the actual index in original array

I tried rewriting recursively and messed up the indexing and completely missed using low/high to compress a window.

so I got it right but I think I failed.
tidied up my comments after testing.
20 mins.

238. I was able to do it, including the ‘overflow’ dangers mentioned on the Google blog. I used pointers instead of indexes so I made sure of this

239. So, tentatively, I want to say that I passed the test. Submission is above and here: http://gist.github.com/371735

Unfortunately, as noted in my gist, I don’t know what I don’t know! I might be iterating too many times, and I don’t know which other cases I should be testing against. Someone needs to put together a test suite for the numerous Python submissions!

240. shezi

Aaand there it is: Failure to read the specification. I only search for values in the array. Cheers for me, I’m part of the 90%.

241. wallygold

I had one bug that prevented me from identifying the value stored at the end of the array i.e. the largest value. Fixing it was pretty simple.

I have the 2nd edition of the book and every year and a half or so I come across this very section and end up re-coding it. Usually, I make a careless error. Never takes more than a few minutes to fix.

242. Argh… my first call to splice should use \$pos rather than \$pos-1 because it’s the length of the sub-list rather than the position of the end of the sub-list.

243. Eddie

Here’s my attempt at a recursive version in ruby.

```def binary_search(array, element, low = 0, high = array.length-1)
raise ArgumentError unless Range.new(0,array.length-1).include? low
raise ArgumentError unless Range.new(0,array.length-1).include? high

return high if array[high] == element
return low if array[low] == element
return nil if low >= high

mid = (low+high)/2
return binary_search(array, element, low, mid) if element <= array[mid]
return binary_search(array, element, mid+1, high) if element > array[mid]
nil
end
```
244. Alan

I think my attempt works. I first wrote it as a “contains” check before I realized the point of the task was to find the right index. Because I didn’t think enough before patching it accordingly I actually created an off-by-one error.

I find the requirements a bit harsh, though, because I’ve made it a habit to code with a Python shell open next to my text editor and writing in both, testing my logic and assumptions as I write the code.

I guess I’m not one of the 10 percent then, if only because I test my code rather than mentally parsing it line for line to check for errors prior to testing.

```def search(seq, k):
j = 0
while len(seq) > 0:
i = len(seq)//2
if seq[i] == k:
return j+i
if seq[i] > k:
seq = seq[:i]
else:
seq = seq[i+1:]
j += i+1
return None
```
245. Jaisen Mathai

{source}var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19];
var count = 0;

function bsearch(arr, lookup)
{
console.log(arr);
count++;
if(count > 100)
return ‘endless recursion?’;

if(arr.length == 1)
return arr[0] == lookup ? arr[0] : false;

var midpoint = parseInt(arr.length / 2);
if(arr[midpoint] == lookup) {
return arr[midpoint];
} else if(arr[midpoint] > lookup) {
return bsearch(arr.slice(0, midpoint), lookup);
} else {
return bsearch(arr.slice(midpoint, arr.length), lookup);
}
}

console.log(bsearch(arr, 9));{/source}

246. Correction. My code did not work with an empty list.

Here is the corrected code.

[SOURCE]
template
RIt binary_search(const RIt &first, const RIt &last, const T &val)
{
RIt a = first;
RIt b = last;
for(;;)
{
RIt::difference_type diff = b-a;
if (diff==1)
{
if (*a==val) return a;
return last;
}
RIt c = a+diff/2;

if (val<*c) b = c;
else a = c;
}
}
[/SOURCE]

Works with any type T that is less than comparable. And it works with random access iterators (such as pointers or vector iterators).

247. ```template
RIt binary_search(const RIt &first, const RIt &last, const T &val)
{
RIt a = first;
RIt b = last;
for(;;)
{
RIt::difference_type diff = b-a;
if (diff==1)
{
if (*a==val) return a;
return last;
}
RIt c = a+diff/2;

if (val<*c) b = c;
else a = c;
}
}
```
248. Daniel Rogers

This one is in javascript. Untested. 45 minutes (approx).

function binary_search(t,a) {
return binary_search_helper(t,a,0,a.length);
}

function binary_search_helper(t,a,start,end) {
/*
* assume start is untested
* assume end is also tested and does not contain the element
*/
if (start === end) {
return null;
}
/*
* only one element left to find
*/
if (end-start === 1) {
return t === a[start]?a[start]:null;
}
/*
* end-start is at least 2 (since it is neither 0 or 1
* from the conditions above), thus Math.floor((end-start)/2)
* >=1.
*
* this is important to prevent an infinite loop
*/
var middle = start + Math.floor((end-start)/2);
/*
* a[middle-1] makes sure we look for the first occurance
* middle>=1 since end-start is at least 2 and start is >=0
*/
if (a[middle] === t && a[middle-1] != t) {
return middle;
}
if (a[middle] <== t) {
return binary_search(t,a,middle+1,end);
}
/*
* also covers the case where a[middle-1] === t
* (i.e. we found the element but it's not the least
* element)
*/
return binary_search(t,a,start,middle);
}

249. Daniel Hanson

Submitted without testing. The function returns the length of the array if the value cannot be found.

```size_t bsearch(int *array, size_t length, int value)
{
size_t begin = 0;
size_t end = length;

while (begin < end)
{
size_t mid = (end - begin) / 2 + begin;
if (value < array[mid]) end = mid;
else if (array[mid] < value) begin = mid + 1;
else return mid;
}

return length;
}```

I forgot to test for an empty list. So my code wasn’t correct the first time around as I had thought.

```template<class RIt, class T>
RIt binary_search(const RIt &first, const RIt &last, const T &val)
{
if (first==last) return last;  // I had forgotten this line.
RIt a = first;
RIt b = last;
for(;;)
{
RIt::difference_type diff = b-a;
if (diff==1)
{
if (*a==val) return a;
return last;
}
RIt c = a+diff/2;

if (val<*c) b = c;
else a = c;
}
}
```

Works with any type T that is less than comparable. And it works with random access iterators (such as pointers or vector iterators).

[Mike says: if you really want me to, I will delete your other comments. But I would prefer to retain them, because your successive iterations are instructive.]

251. BjoernD

I failed. Got updating the pivot index wrong the first time.

My current code succeeds with my tests. (And is ugly…)

Time to first version: ~10 min
Time to fix bugs: ~20 min

```#define FAIL do { return -1; } while (0)

int binsrch(int *a, int len, int v)
{
int low = 0;
int high = len-1;

// zero element array?
if (high < low)
FAIL;

int diff = high - low;
int p = low + diff / 2;

do {
// success!
if (a[p] == v)
return p;

if (v < a[p])
high = p-1;
else
low = p+1;

diff = high - low;
p = low + diff/2;

} while (diff > 0);

if (a[p] == v)
return p;

FAIL;
}
```
252. The really humbling thing isn’t how hard it is to write correct code without testing, but how long it takes, even for a simple textbook algorithm. Binary search is the sort of thing that sounds like it should take five minutes, but I took 45, and I don’t think I was distracted for more than 5 minutes of that. At least a third of the time was due to the added complexity of usefully supporting arbitrary types and orderings, not just numbers in ascending order. Here it is (in Common Lisp):

```(defun bsearch (target vec &key (key #'identity) (order #'<) (test #'eql))
"Given a vector VEC sorted in ORDER by KEY, return an element whose KEY is equal (by TEST) to TARGET, or NIL.
ORDER must be a total ordering - equivalent elements are not allowed.
Examples:
(bsearch 1/2 #(-1 3 2 1) :key #'/ :test #'=) => 2
(bsearch 5 #(1 2 4 8)) => nil
(bsearch 1 #((2 two) (1 one)) :key #'car :order #'>) => (1 ONE)
(bsearch 1 #(() (a) (a a)) :key #'length :test #'equalp) => (A)"
(labels ((bs (start end)
(if (>= start end)
nil
(let* ((probe (floor (+ start end) 2))
(pivot (funcall key (elt vec probe))))
(cond ((funcall test target pivot) (elt vec probe))
((funcall order target pivot) (bs start probe))
(t (bs (1+ probe) end)))))))
(bs 0 (length vec))))```

It has passed all my tests so far. However, I’m not sure this counts entirely as a success, because I reinterpreted the requirements to make it easier: I originally intended to allow equivalent elements in the ordering, but when I realized that was awkward, I just gave up and declared that the ordering had to be total.

253. Chris Lamberson

I’ll try my hand at this. Here’s the code *before* testing (python):

```def binsearch(lst, target):
pivot = len(lst)/2
left, center, right = lst[:pivot], lst[pivot], lst[pivot+1:]
if target == center:
return center
elif target < center:
return binsearch(left, target)
else:
return binsearch(right, target)
```

Let me know if I screwed it up! Pretty sure it works though…

254. Dan Lidral-Porter

I believe this code is correct . Ultimate shame on me if there are any bugs remaining.

```
-module(bsearch).
-export([bsearch/2).

bsearch(List, N) ->
io:format("searching ~w for ~w~n", [List, N]),
Length = length(List),
if
Length == 0 ->
not_found;

true ->
bs_rec(List, N, 1,length(List))
end.

bs_rec(List, Goal, Start, Stop) ->
Mean = erlang:trunc((Start + Stop) / 2),
Nth = lists:nth(Mean, List),

if
Start == Stop ->
if
Nth == Goal ->
{Goal, Mean};

true ->
not_found
end;

Start > Stop ->
not_found;

Nth < Goal ->
bs_rec(List, Goal, Mean + 1, Stop);

Nth == Goal ->
{Goal, Mean};

Nth > Goal ->
bs_rec(List, Goal, Start, Mean-1)
end.
```
255. PHP:

```<?php
function binarySearch(\$needle, \$haystack) {
\$start = 0;
\$end = count(\$haystack);
while ((\$end - \$start) > 1) {
\$mid = \$start + floor((\$end - \$start) / 2);
if (\$haystack[\$mid] > \$needle) {
\$end = \$mid;
} elseif (\$haystack[\$mid] < \$needle) {
\$start = \$mid;
} else {
return \$mid;
}
}
return false;
}
?>```

256. PHP, didn’t check this at all, thought it would be fun.

```<?php
function bsearch(\$search, \$array, \$start, \$end){
//\$start cannot be zero. -1 = not found, otherwise returns index of \$search in \$array
//\$search not in \$array
if(\$start>\$end){
return -1;
}
//calculate middle
\$middle = \$start + ceil((\$end-\$start)/2);
//check match
if(\$array[\$middle]==\$search){
return \$middle;
}
//is the middle higher than the search, if so, cut top
else if(\$array[\$middle]>\$search){
return bsearch(\$search, \$array, \$start, \$middle-1);
}
//otherwise cut bottom
else{
return bsearch(\$search, \$array, \$middle+1, \$end);
}
}

?>
```
257. John Gunderman

```bsearch :: (Ord a) => a -> [a] -> Bool
bsearch elem (x:[]) = if x == elem
then True
else False
bsearch elem xs = if elem >= head second
then bsearch elem second
else bsearch elem first
where mid = length xs `div` 2
t = splitAt mid xs
first = fst t
second = snd t
```

This works properly. However, I must admit I initially failed. The mistake was completely stupid as well; in the line reading

```t = splitAt mid xs
```

```t = splitAt 0 xs
```

Which makes me feel quite stupid :) fortunately, that seems to be the only error I can find. Let me know if you find any other errors.

258. n

How about a nice Fortran implementation :-)

```PROGRAM bs

INTEGER :: list(12) = (/1, 3, 6, 11, 125, 345, 985, 1011, 2111, 2122, 3000, 4051 /)
INTEGER :: target   = 11
INTEGER :: ans      = -1

CALL search(1, SIZE(list))

PRINT *,ans

CONTAINS

RECURSIVE SUBROUTINE search(lower, upper)

INTEGER :: middle, upper, lower

middle = lower + NINT((upper - lower)/2.0)

IF (list(middle) == target) THEN
ans = middle
RETURN
ELSE IF(list(middle) &gt; target) THEN
CALL search(lower, middle)
ELSE IF(list(middle) &lt; target) THEN
CALL search(middle, upper)
END IF

END SUBROUTINE search

END PROGRAM bs

```
259. Jack

I ran a few small tests – seems to work ok. Writen in C.

int bin_search(int a[], size_t sz, int item)
{
int l_bound = 0;
int u_bound = sz-1;
int current;

if (item == a[l_bound]) return l_bound;
if (item == a[u_bound]) return u_bound;
while (l_bound + 1 < u_bound) {
current = (l_bound + u_bound)/2;
if (item == a[current]) return current;
else if (item < a[current]) u_bound = current;
else l_bound = current;
}
return -1;
}

260. x

Did half-assed testing (which passed). No code changes after testing

```def bsearch(val, sorted_seq):
"""
Use a binary search on sorted_list to find val.

Args:
val: a value that could appear in sorted_list.
sorted_seq: some sort of container that supports __len__ and __getitem__
Returns:
either the integer index the element is at or None
"""

# pre-loop
try:
assert val <= val
assert val >= val
assert val == val
except AssertionError:
raise ValueError("val does not pass basic equality tests")

min_index = 0
max_index = len(sorted_seq)

# simple loop - no optimization checks
while min_index < max_index:
mid = (max_index + min_index) / 2

mid_val = sorted_seq[mid]
if val == mid_val:
return mid
elif val < mid_val:
max_index = mid - 1
elif val > mid_val:
min_index = mid + 1
else:
raise ValueError("val does not properly compare to element %s" % str(mid_val))

# couldn't find val
return None
```
261. Kemal

In Python, using slicing and tail recursion. Passes unit tests of all the usual suspects.

No guarantees of efficiency

```from __future__ import division

import math

def binsearch(element, mylist):
return find_helper(element, mylist, 0)

def binsearch_helper(element, mylist, first_index):
length = len(mylist)
if length == 0: return None
if length == 1:
if mylist[0] == element: return first_index
else: return None
mid = int(math.floor(length / 2))
if mylist[mid] == element: return mid + first_index
if element < mylist[mid]: return find_helper(element, mylist[0:mid], first_index)
return find_helper(element, mylist[mid:], first_index + mid)
```
262. bey0ndy0nder

Okay, I wrote it out on paper and worked out a few cases, then I just went out and wrote code + some tests. Probably has some bugs. And it’s ugly also. I fully admit that is a hack.

//tail recursion
int binSearch(int lo, int hi, int range, int theNumber, int sortedArray[])
{
int retIdx = -1;
if(range==2) //sort of whack…
{
if(sortedArray[lo] == theNumber)
return lo;
else if(sortedArray[hi] == theNumber)
return hi;
else
}
else if(range == 1)
{
if(sortedArray[lo] == theNumber)
return lo;
else
return -1;
}
int divider = lo + range/2;
if(sortedArray[divider] == theNumber)
return divider;
else if(theNumber < sortedArray[divider]) //recurse left
{
return binSearch(lo,divider-1,divider-lo,theNumber,sortedArray);
}
else //recurse right
{
return binSearch(divider+1,hi,hi-divider,theNumber,sortedArray);
}
}

Tests:

```random_shuffle(randIdx.begin(), randIdx.end());

cout << "Sorting array to prepare for binary search. " << endl;
std::sort(massiveArrayOfInts, massiveArrayOfInts+massiveNumber);

//First, try to find all matches in the array.
foundCount = 0;
for(int i=0; i < massiveNumber; ++i)
{
int retIdx = binSearch(0,massiveNumber-1,massiveNumber,massiveArrayOfInts[randIdx[i]],massiveArrayOfInts);
if(retIdx >= 0)
foundCount++;
}

cout << "Done binSearch. Foundcount is: " << foundCount << endl;
if(foundCount == massiveNumber)
{

cout << "Foundcount: " << foundCount << " this means you win! A MASSIVE WIN! (Are you sure?)" << endl;
}
```
263. Alex Ati

Wrong! But it’s very late and i’m coding while lying in my bed, not in the office :P

```(defun binary-search (elt list)
(binary-search-1 elt list 0 (- (length list) 1)))

(defun binary-search-1 (elt list first last)
(cond
((= first last)
(if (= elt (nth first list)) first nil))
((< first last)
(let ((mid (/ (+ first last) 2)))
(cond
((= elt (nth mid list)) mid)
((< elt mid)
(binary-search-1 elt list first (- mid 1)))
(t
(binary-search-1 elt list (+ mid 1) last)))))))

```
264. vault_

Okay, I came up with a nominally tested ruby implementation using recursion. Had an off by one error that led to infinite recursion, but I think that’s fixed now.

```def binsearch x, arr
if arr.size == 0
false
elsif arr[arr.size/2] == x
true
else
arr[arr.size/2] > x ? binsearch(x,arr[0...arr.size/2])
: binsearch(x,arr[(arr.size+1)/2...arr.size])
end
end

```
265. Okay, about to test. I should say I’ve written binary search a number of times in the past and got it wrong a number of ways and fixed it. So I have specific personal rules (which I won’t reveal at this time) about writing binary search!

But in this case I first wrote a very simple linear_search() function, then a tester, then a broken_search() function to make sure the tester actually catches the bugs it’s looking for. In that step I came across a bug I hadn’t tested for: not returning the ( i, nsteps ) tuple that the tester expects. So I must admit I had practice making and fixing that error. My code, alternate searchers, and tester are here. Note that I fleshed out Bentley’s spec to my own liking.

```def binary_search( A, T ):
"""\
Return i, nsteps.
i is any int such that A[i] == T, else i = None
nsteps is the number of steps it took.
"""
imin, ilimit = 0, len(A)
nsteps = 0
while imin < ilimit:
nsteps += 1
i = imin + ( ilimit - imin ) / 2
if A[i] == T:   return i, nsteps

elif A[i] < T:  imin   = i + 1
else:           ilimit = i

return None, nsteps

def linear_search( A, T ):
""" Return i, nsteps
i == first index such that A[i] == T, else i = None
nsteps is the number of steps taken.
"""
indexes = [ i for i in range( len(A) ) if A[i] == T ]
if indexes: return indexes[ 0 ], len(A)
else:       return None,         len(A)

```
266. Ralph

Matlab code:

B = floor(rand(50,1)*100)
T = 7
A = sort(B)
Found = 0

while (length(A)>0)
j = ceil(length(A)/2)
if (A(j) > T)
if (j ==1)
A = [];
else
A = A(1:(j-1));
end
elseif (A(j)<T))
if (j==length(A))
A = [];
else
A = A((j+1):length(A))
end
else
Found = 1;
A = [];
end
end

if (Found ==1)
display('found the target number')
else
end

will test it in a second :)

267. Tim

GO GO GADGET BINARY SEARCH FUNCTION:

int binarySearch(int* array, int arraySize, int value)
{
int currentMax = arraySize-1;
int currentMin = 0;
int index;

if( !array || arraySize <= 0 )
return -1;

while(1)
{
index = ((currentMax – currentMin) / 2) + currentMin;

if( *(array+index) == value )
return index;
else
{
if( *(array+index) < value )
{
currentMin = index + 1;
}
else
{
currentMax = index – 1;
}
}

if( currentMax < currentMin )
return -1;
}
}

268. A simple ruby script which take arguments from command line. The search is the first number, the following numbers are the array.

```#!/usr/bin/env ruby

def rec_binsearch( tab, search, min, max )
if min < max
return -1
end
med=(max + min)/2
if tab[med] == search
return med
end
if tab[med] =0
puts %{tab[#{res}]=#{tab[res]}}
else
puts %{can't find #{search} in [#{tab.join(' ')}]}
end
```
269. Okay, mine passes my tests!

```Testing binary_search

Took 0 steps for 588 problems, smallest of size 0
Took 1 steps for 538 problems, smallest of size 1
Took 2 steps for 497 problems, smallest of size 2
Took 3 steps for 461 problems, smallest of size 4
Took 4 steps for 512 problems, smallest of size 8
Took 5 steps for 489 problems, smallest of size 16
Took 6 steps for 441 problems, smallest of size 32
Took 7 steps for 383 problems, smallest of size 65
Took 8 steps for 187 problems, smallest of size 128

That was a test of binary_search
```
270. Kemal

I stupidly changed the name of the function after posting it to the comment box, but neglected to change the calls. Maybe that counts as failing?

Anyways, here’s the correct version. Also, I just use default arguments instead of a helper function.

```from __future__ import division

import math

def binsearch(element, mylist, first_index=0):
length = len(mylist)
if length == 0: return None
if length == 1:
if mylist[0] == element: return first_index
else: return None
mid = int(math.floor(length / 2))
if mylist[mid] == element: return mid + first_index
if element < mylist[mid]: return binsearch(element, mylist[0:mid], first_index)
return binsearch(element, mylist[mid:], first_index + mid)
```
271. Wrick

public class BinSearch {

/**
* Search for b in sorted (ascending) array a
*/
public static int binSearch(int a[], int b) {
if(a == null || a.length == 0)
return -1;

int min = 0, max = a.length-1;

while(min <= max) {
int mid = (min+max+1)/2;
if(a[mid] b)
max = mid;
else
return mid;
}

return -1;
}
}

272. Here’s my attempt in Ruby. Haven’t tested it yet, but I’ll be doing that shortly.

```def binary_search(arr, obj, lower=0, upper=nil)
upper = arr.length - 1 if upper.nil?

pivot = (lower + upper) / 2
return pivot if arr[pivot] == obj

if upper - lower == 1
return upper if arr[upper] == obj
return nil
end
return nil if upper - lower == 0

return binary_search(arr, obj, lower, pivot) if arr[pivot] >; obj
return binary_search(arr, obj, pivot, upper) if arr[pivot] < obj
end
```
273. Ian
```
Defends against gremlins that I can think of. No idea if zero length arrays are valid in C# but I don't want to find out :D ps, it compiles with a zero length array defined but unused.

public static int search(int[] haystack, int needle)
{
int[] test = new int[0];
int low = 0;
int high = 0;
if (haystack.Length > 0)
{
high = haystack.Length - 1;
}
else
{
return -1; //Can't find anything in an array with no entries.
}
int midpoint = 0;

//If only searching smaller arrays (less than 10000 entries ish), feel free to skip this part.
if (needle < haystack[low] || needle > haystack[high])
{
return -1; //needle is smaller or larger than our values, no point searching.
}

while (low < high)
{
midpoint = low + (high - low)/2;
if (needle > haystack[midpoint])
{
low = midpoint + 1;//Smallest possible is by definition at least one larger.
}
else {
high = midpoint;//Largest it could possibly be is midpoint.
}
}
if (needle == haystack[midpoint])
{
return midpoint;
}
else
{
return -1; //Did not find needle in haystack.
}
}
```
274. Jason Spencer

Hey, sounds fun. I love a good challenge. I’m writing this in a text editor to avoid reading any previous comments that have come in since I read the article. Below is my implementation in Python 3 syntax (it “compiles” without errors). I have to say, it’s very hard not to test this before posting! I’m a bit of a novice, so I don’t expect this to be bug free. Go easy on me.

```#/usr/bin/env python3

def binarySearch(search, list, middle=None, low=0, high=None):
if len(list) == 0:
return
if high == low:
return
if high == None:
high = len(list)
if middle == None:
middle = len(list)//2
if search == list[middle]:
return middle
if search > list[middle]:
# search top
low = middle
middle = (((high - middle) // 2) + middle)
else:
#search bottom
high = middle
middle = (((middle - low) // 2) + low)
return binarySearch(search, list, middle, low, high)```
275. Wrick
```public class BinSearch {

/**
* Search for b in sorted (ascending) array a
*/
public static int binSearch(int a[], int b) {
if(a == null || a.length == 0)
return -1;

int min = 0, max = a.length-1;

while(min &lt; max) {
int mid = (min+max)/2;
if(a[mid] <b> b)
max = mid;
else
return mid;
}

return -1;
}
}
```
276. Wrick
```public class BinSearch {

/**
* Search for b in sorted (ascending) array a
*/
public static int binSearch(int a[], int b) {
if(a == null || a.length == 0)
return -1;

int min = 0, max = a.length-1;

while(min < max) {
int mid = (min+max)/2;
if(a[mid] < b)
min = mid + 1;
else if(a[mid] > b)
max = mid;
else
return mid;
}

return -1;
}
}
```
277. Drew Benedetti

I had to look up the syntax of ldiff, and initially forgot to floor mdx. That got it running, but it turns out I forgot to handle values that aren’t found.

```(defun bsearch (x range &optional (start 0))
(let* ((mdx (floor (/ (length range) 2)))
(mid (nth mdx range)))
(cond ((= mid x) (+ start mdx))
((< mid x) (bsearch x (nthcdr (1+ mdx) range) (+ start mdx 1)))
((> mid x) (bsearch x (ldiff range (nthcdr mdx range)) start)))))
```

I realize using nthcdr and ldiff is probably extremely terrible.

278. bey0ndy0nder

Just some quick thoughts….It’s given that the length is either odd or even. Thus, as one recurse it eventually all broil down to an Odd middle index or and Even middle index.

279. Alex

Worked perfectly from the very start:

```#include <stdio.h>

int binary_search(int * in, int length, int to_find)
{
int left_bound = 0;
int right_bound = length;
while (1) {
int current = left_bound + ((double) right_bound - left_bound)/2;

if (in[current] == to_find) {
return current;
}
if (left_bound >= right_bound) {
return -1;
}
else if (in[current] < to_find) {
left_bound = current + 1;
} else if (in[current] > to_find) {
right_bound = current - 1;
}
}

return -1;
}
```
280. SuperSlug

Untested… this was a good exercise!

```def bsearch(a, t):
start = 0
end = len(a) - 1
while	start &lt;= end:
middle = (start + end) / 2
if a[middle] == t:
return middle
elif a[middle] &lt; t:
start = middle + 1
else:
end = middle - 1
return -1
```
281. dijit

Oops, it didn’t work on the empty array case. But other than that it worked.

282. SuperSlug2

Untested… this was a good exercise!

```def bsearch(a, t):
start = 0
end = len(a) – 1
while start <= end:
middle = (start + end) / 2
if a[middle] == t:
return middle
elif a[middle] < t:
start = middle + 1
else:
end = middle – 1
return -1
```
283. Robert Græsdal

ECMAScript implementation, using a small recursive function.

I didn’t look at others source code, no looking at other binary search routines and no testing until it was done.

This code makes a small dictionary tree and searches for words you put in.

```javascript:
var tree = {
item:"m",
value:"Delicious candy!",
i0:{
item:"aardvark",
value:"Some kind of animal?"
},
i1:{
item:"roof",
value:"It keeps the pesky sun out",
i0:{
item:"protection",
value:"We're the mafia!"
},
i1:{
item:"zero",
value:"Definition: You."
}
}
};

function bsearch(T,N){
if( N == null)
return null;
else if(T > N.item)
return bsearch(T,N.i1);
else if(T < N.item)
return bsearch(T,N.i0);
else if(T == N.item)
return N;
}

284. Jeremiah Via

```search :: (Ord a) =&gt;  a -&gt; [a] -&gt; Maybe a
search _ [] = Nothing
search v xs
| v == middle xs = Just v
| v   middle xs = search v (tail xs)
where middle ys  = ys !! (length ys `div` 2)
```

Matthias Goergens’ solution makes me realize that there is a lot of Haskell learning to do.

285. anonymous

failure!

286. ```def binarysearch(lst, item, start=0, end=None):
"""returns None if it cannot find item in lst, otherwise returns the index"""
if end is None:
end = len(lst) #end is non-inclusive

if end <= start:
return None

mid = start + (end - start) // 2

if item < lst[mid]:
return binarysearch(lst, item, start, mid)
elif item > lst[mid]:
return binarysearch(lst, item, mid+1, end)
else:
return mid
```
287. Here is a VB.NET version that is tested. I failed a few cases on the first try. Biggest mistake was an off by one error. This is a rewrite to remove all the unnecessary code and fix all the edge cases.

```    Function BinarySearch(ByVal a() As Integer, ByVal x As Integer) As Integer

Dim min As Integer = 0
Dim max As Integer = a.Length - 1
Dim mid As Integer = 0

While max >= min
mid = min + (max - min) / 2
If a(mid) = x Then
Return mid
ElseIf a(mid) < x Then
min = mid + 1
ElseIf a(mid) > x Then
max = mid - 1
End If
End While

Return -1

End Function

Sub Main()

Dim a() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}

For i As Integer = 0 To 21
System.Console.WriteLine(String.Format("{0} is at {1}", i, BinarySearch(a, i)))
Next

End Sub

```
288. Fred

Tested, and seems to work. Got it first try.

```<?
function binary_search(\$needle,\$haystack) {
\$begin = 0;
\$end = count(\$haystack) - 1;

if (\$needle > \$haystack[\$end] || \$needle < \$haystack[\$begin]) {
return false;
}

\$done = false;

while(!\$done) {
\$split = (\$end - \$begin)/2 + \$begin;

if (\$haystack[\$split] == \$needle) {
\$found = true;
\$done = true;
} else if (\$haystack[\$split] > \$needle) {
\$end = \$haystack[\$split - 1];
} else if (\$haystack[\$split] < \$needle) {
\$begin = \$haystack[\$split + 1];
} else {
\$done = true;
\$found = false;
}
}

return \$found;
}
?>
```
289. Testing is part of software development. This challenge is a bit like asking artists to draw a perfect circle while blindfolded. It’s a neat parlor trick, but you can’t use it as a litmus test for a “real artist” or “real programmer.”

Anyhow; I saw that someone already posted an overly-generic C# IEnumerable solution, so I wasn’t going to post mine. But since the earlier solution uses the ElementAt extension method, mine is still notable in the “overkill” category.

```      static T bsearch<T>(T wanted, IEnumerator<T> iter, int count) where T : IComparable
{
if (count <= 0 || iter.Current == null)
return default(T);

if (count == 1)
if (wanted.CompareTo(iter.Current) == 0)
return iter.Current;
else
return default(T);

List<T> seen = new List<T>();
for (int ii = 0; ii < count / 2; ii++)
{
if (!iter.MoveNext())
return default(T);
}

int result = wanted.CompareTo(iter.Current);
if (result == -1)
return bsearch(wanted, seen.GetEnumerator(), count / 2);
else if (result == 0)
return iter.Current;
else
return iter.MoveNext() ? bsearch(wanted, iter, count - (count / 2) - 1) : default(T);
}
```
290. ```public class BinarySearch {
public static <T extends Comparable<? super T>> int search(final T value, final T[] values) {
int index = -1;
int low = 0;
int high = values.length;
int mid = -1;

while (index < 0) {
mid = (low + high)/2;
if (values[mid].compareTo(value) > 0) {
if (high == mid) {
break;
} else {
high = mid;
}
} else if (values[mid].compareTo(value) < 0) {
if (low == mid) {
break;
} else {
low = mid;
}
} else {
index = mid;
}
}

return index;
}
}```

untested, java

291. Joe User

ok, so after about 25 minutes,

basic psuedo code is

return index if good
return go_left(lower, index-1) if less good
else return go_right(index+1, upper)

I have not tested the following code…

```def bsearch(lower, upper, value, arr):
index = int((lower+upper)/2)
if  (arr[index] == value):
return index
if (arr[index] < value):
return bsearch(lower,index-1,value,arr)
else:
return bsearch(index+1,upper,value,arr)

main(low_to_high_sorted_arr, value):
return bsearch(0, len(arr)-1, value, arr)

```

10 minutes later the above is typed in.

Looks like more specific psudocode, but is hopefully well formed python.

This assumes either that the value is unique, or that we don’t care which index is returned for multiple.

Mind you I’ve done this in school previously, so it was good reminder.

If I had more time I’d step through with a couple of cases. Maybe even test it in an actual interpreter.

292. anonymous
293. Bernard

Here’s my attempt at a recursive D (D 2.0) version:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 /** * An implementation of the binary search algorithm for */ module bsearch; /** * Performs a binary search over list 'l' for element 'e'. * Returns the index, or -1 on failure. * * 'base' is for internal use by the function. * * The return value should be size_t, but we are allowed to ignore overflow. */ int bsearch(T)(T[] l, T e, int base = 0) { int index(int i) { return base + i; } if (l.length == 0) return –1; if (l.length == 1) { if (l[0] == e) { return index(0); } else { return –1; } } size_t mid = l.length / 2; if (e == l[mid]) { return index(mid); } else if (e < l[mid]) { return bsearch(l[0 .. mid], e, 0 + base); } else if (e > l[mid]) { return bsearch(l[mid .. \$], e, mid + base); } // We shouldn't reach here. assert(false); } void main() { } unittest { int[] l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; assert(bsearch(l, 5) == 4); assert(bsearch(l, 1) == 0); assert(bsearch(l, 10) == 9); assert(bsearch(l, 11) == –1); assert(bsearch(l, 0) == –1); int[] ll = [5]; assert(bsearch(ll, 5) == 0); assert(bsearch(ll, 6) == –1); assert(bsearch(ll, 4) == –1); ll ~= 6; assert(bsearch(ll, 5) == 0); assert(bsearch(ll, 6) == 1); assert(bsearch(ll, 7) == –1); assert(bsearch(ll, 4) == –1); int[] z = []; assert(bsearch(z, 1) == –1); }

view raw

bsearch.d

hosted with ❤ by GitHub

```/**
* Performs a binary search over list 'l' for element 'e'.
* Returns the index, or -1 on failure.
*
* 'base' is for internal use by the function.
*
* The return value should be size_t, but we are allowed to ignore overflow.
*/
int bsearch(T)(T[] l, T e, int base = 0)
{
int index(int i)
{
return base + i;
}

if (l.length == 0) return -1;
if (l.length == 1) {
if (l[0] == e) {
return index(0);
} else {
return -1;
}
}

size_t mid = l.length / 2;
if (e == l[mid]) {
return index(mid);
} else if (e < l[mid]) {
return bsearch(l[0 .. mid], e, 0 + base);
} else if (e > l[mid]) {
return bsearch(l[mid .. \$], e, mid + base);
}

// We shouldn't reach here.
assert(false);
}
```

It passes my tests (see the gist) but I’m sure I’ve missed an edge condition or four.

294. ```def bsearch(needle, haystack, lo, hi):
if hi - lo == 0:
return False
elif hi - lo <= 1:
return haystack[lo] == needle

mid = (lo + hi) // 2

if haystack[mid] == needle:
return True
elif haystack[mid] < needle:
return bsearch(needle, haystack, mid, hi)
else:
return bsearch(needle, haystack, lo, mid)

import random
arr = [ random.randint(1,100) for _ in range(100) ]
arr.sort()

for e in range(100):
assert (e in arr) == bsearch(e, arr, 0, 100)
```
295. Can someone test mine? I’m too lazy to. -.-

296. ```class MyArray  range_end

middle = ((range_end - range_start) / 2) + range_start

return -1 if self[middle].nil?

if needle > self[middle]
index_of_recurse(needle, middle + 1, range_end)
elsif needle < self[middle]
index_of_recurse(needle, range_start, middle - 1)
else
return middle
end
end
end
```

Success–but I did it recursively, which I consider kind of a fail given the use case.

297. Robert Græsdal

I notice I’ve misunderstood the task. I should have worked on an array and not a tree structure.

298. andrew
```#!/usr/bin/perl
use POSIX qw(floor);

sub binSearch(\$\@)
{
my \$value = shift;
my @data = @{(shift)};

return (\$value == \$data[0])
if(0 == \$#data);

my \$cutPoint =
floor((\$#data+1)/2.0);

if(\$value < \$data[\$cutPoint])
{
my @lft = splice(@data,0,\$cutPoint);
return binSearch(\$value,\@lft);
}

my @rgt = splice(@data,\$cutPoint);
return binSearch(\$value,\@rgt);
}

my @data = (1,19,29,38,38,38,41,42,59,199);

if(binSearch(42,@data))
{
print "found\n";
}
else
{
print "unfound\n";
}
```
299. I’m going to do the “extra credit” macho option and post my solution before testing it. (I did run a syntax check, and I did mentally trace through a number of cases first.)

```;;; Searches vector v for element e with the less-than procedure lt,
;;; returning its index if found, else #f
(define (binary-search v e (lt string<?))
(define (search a c)
(if (= a c) #f
(let* ((b (truncate (/ (+ a c) 2)))
(m (vector-ref v b)))
(cond
((lt e m) (search a b))
((lt m e) (search (+ b 1) c))
(else b)))))
(search 0 (vector-length v)))
```
300. ```int search(int v, int[] p)  {
int i = 0;
int j = p.size;
while (j - i)  {
int n = (j-i) / 2 + i;
if (p[n] > v)
i = n + 1;
else
j = n;
}
return (p[i] == v) ? i : -1;
}
```

I wrote this from memory – but as I wrote an assembler version only a few weeks ago, the technique is still fresh in my mind – and specifically the use of array.size as the upper bound, rather than array.size-1.

Scanning through the other comments, seems like this one is very similar.

301. K

I failed – simple bug, but failure none the less.

However, I don’t really see a point in this exercise – are you(or the author of the book) implying that if a programmer can’t implement this on first try, without testing, he’s not as good as one who can?

IMO, it’s not a good metric for the ability of the programmer.

Now, if a programmer doesn’t _understand_ the binary search algorithm after reading it – then we might have a problem…

302. Tested and seems to work in ruby, looking for the bug after posting comment:

```max_range = rand(1000)
range = [1...max_range]
T = rand(max_range)

puts "mac_range: #{max_range}"
puts "rand T = #{T}"

while(range.empty?)
T = ceil(range.size / 2)
if T == range[T]
break
elsif T < range[T]
range[1...T]
else
range[T...max_range]
end
end

puts "T = #{T}";
```
303. Alex
```public class BinSearch {
public static void main(String[] args) {
int[] arg = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(binSearch(arg, 5));
System.out.println(binSearch(arg, 0));
System.out.println(binSearch(arg, 8));
System.out.println(binSearch(arg, 10));
System.out.println(binSearch(arg, -1));
System.out.println(binSearch(arg, 11));

for(int i = 0; i <= 9; i++) {
System.out.println(binSearch(arg, i));
if(i != binSearch(arg, i))
System.out.println("Failed test!");
}
}

public static int binSearch(int[] arr, int n) {
if(arr == null)
throw new NoSuchElementException();

int high = arr.length-1;
int low = 0;

int tmp;
while(true) {
tmp = arr[(high-low)/2 + low];
// If tmp is less than n, set params to second half
if(tmp < n) {
low = ((high-low)/2 + low)+1;
}
// If tmp is greater than n, set params to first half
else if(tmp > n) {
high = ((high-low)/2 + low)-1;
}
// if tmp is n, return true
else {
return tmp;
}

// if the bounds are less than 4, save us all a headache and just seqsearch it
if(high-low <= 4) {
for(int i = low; i <= high; i++) {
if(arr[i] == n)
return i;
}
return -1;
}
}
}```

I think I passed, but I didn’t test.

Question, though: if we all know that only 10% of people passed this test, won’t we also try harder, thus skewing the results? A balanced experiment would be double-blind.

304. Alex

Thoroughly. I mean I didn’t test thoroughly. Just FYI.

305. Only problem I had when I did my first test was that I forgot to return the results of my recursive call to binary_search.

```import math

def binary_search(target, value, size=None):
if not size: size = len(target)
half_size = int(math.floor(size / 2))
mid = target[half_size - 1]
if mid > value: target = target[:half_size]
elif mid < value: target = target[half_size:]
else: return half_size - 1
return binary_search(target, value, half_size)

test = [1,3,4,7,9,10,22,35,67,365,1000,1024,2010,3000,9000]
find = 22
pos = binary_search(test, find)
print test[pos] == find
```
306. ```def binary_search(needle, haystack):
def recurse(begin, end):
pivot = int((end - begin) / 2) + begin
pivot_value = haystack[pivot]
if needle  pivot_value:
return recurse(pivot + 1, end)
return pivot
return recurse(0, len(haystack))
```

Test suite:

```import random
samples = []
for i in range(0, 1000):
data = set()
count = random.randint(1, 10000)
for j in range(0, count):
data = list(data)
data.sort()
needle = random.choice(data)

samples.append(dict(needle=needle, data=data))

for sample in samples:
correct = sample['data'].index(sample['needle'])
found = binary_search(sample['needle'], sample['data'])
if found == correct:
print 'Success'
else:
print 'Failed on needle: %d. Found %d, should have been %d.' % (sample['needle'], found, correct)
```
307. Frans-Willem Hardijzer

C++ code, not tested or compiled, returns either an index or -1 for not found. Pretty confident it’ll work, let me know if it doesn’t ;)

```int bsearch(int *arr, int len, int find) {
int left=0; //First element in range
int right=len; //Just past last element in range
while (right>left) { //Range is non-empty as long as right&gt;left
int mid=(left+right)/2; //Rounded down automatically
if (arr[mid]>find) {
// mid point is past value to be found, so range is below this
right=mid;
} else if (arr[mid]<find) {
// mid point is before value to be find, so range starts after this
left=mid+1;
} else {
// thus arr[mid]==find
return mid;
}
}
return -1;
}
```
308. When I read “The only way you’ll believe this is by putting down this column right now and writing the code yourself. Try it.” I stopped reading and tried it.

My binary searches worked without error. Although the first test case I wrote made me think it didn’t because it passed in an unsorted array – and the item wasn’t found.

I think the lack of testing is bunk – who writes code without testing it? We need more people that write correct code because they’ve tested it fully. Not more people who submit code without testing because they think they’re one of the 10% who can do it.

Disclaimer:

```
def binary_search(array, char):
start = 0
stop = len(array)-1
not_found = True
while not_found and start <= stop:
middle = ((stop - start) / 2) + start
mid_char = array[middle]
if mid_char == char:
return middle
elif char < mid_char:
stop = middle-1
elif char > mid_char:
start = middle + 1
return -1

import string
character_array = list(string.letters)
character_array.sort()

print "found"
print binary_search(character_array, 'B')
print binary_search(character_array, 'k')
print binary_search(character_array, 'z')
print binary_search(character_array, 'A')
print binary_search(character_array, 'Z')
print binary_search(range(10), 0)
print binary_search(range(10), 1)
print binary_search(range(10), 2)
print binary_search(range(10), 9)

print binary_search(character_array, '%')
print binary_search(character_array, '(')
print binary_search(character_array, '(')
print binary_search(range(10), 10)
print binary_search([], 10)
print binary_search(range(10), "a")
print binary_search(character_array, character_array)
```
309. Ps. I just realized that the not_found variable is redundant – but it doesn’t hurt anything aside from memory usage.

:P

310. Heimy

Code plus tests. Code in less than 5 minutes + another 10 to write the tests and be sure that it did what it should do before running it.

I understand that one can slip a bug into something that is taken for granted, but come on…

```def bsearch(orderedlist, value):
if len(orderedlist) == 0:
return False
middle = len(orderedlist) / 2
mvalue = orderedlist[middle]
if mvalue == value:
return True
elif mvalue < value:
return bsearch(orderedlist[middle+1:], value)
else:
return bsearch(orderedlist[:middle], value)

# datasets
even = (1, 3, 5, 7, 9, 11)     # Even number of items
odd  = (1, 3, 5, 7, 9, 11, 13) # Odd number of items
not_there = (2, 4, 6, 8, 10, 12)

tests = ( # ( haystack, needle(s), expected answer)
( even, 0, False ),  # Looking for values out of the range
( even, 12, False ),
( odd, 0, False ),
( odd, 0, False ),

( even, not_there[:-1], False ), # Looking for values in the range,
( odd, not_there, False ),       # but not in the dataset

( even, even, True ),            # Looking for the values in the
( odd, odd, True ),               # datasets
)

for haystack, needles, expected in tests:
if not isinstance(needles, tuple):
needles = (needles,)
for needle in needles:
if bsearch(haystack, needle) == expected:
print "PASSED: %d in %s?" % (needle, haystack)
```
311. Jason Spencer

Mine (posted above) seems to work. Since we were ignoring numeric overflow I went ahead and assumed we could ignore stack overflow as well. For a real library or to run on an embedded device (I like AVRs) I’d write an explicitly iterative version.

```#/usr/bin/env python3

def binarySearch(search, list, middle=None, low=0, high=None):
if len(list) == 0:
return
if high == low:
return
if high == None:
high = len(list)
if middle == None:
middle = len(list)//2
if search == list[middle]:
return middle
if search > list[middle]:
# search top
low = middle
middle = (((high - middle) // 2) + middle)
else:
#search bottom
high = middle
middle = (((middle - low) // 2) + low)
return binarySearch(search, list, middle, low, high)

print(binarySearch(0, []))
print(binarySearch(1, [1]))
print(binarySearch(2, [2,4,6,12]))
print(binarySearch(4, [2,4,6,12]))
print(binarySearch(6, [2,4,6,12]))
print(binarySearch(12, [2,4,6,12]))
print(binarySearch(2, [2,4,6,12,13]))
print(binarySearch(4, [2,4,6,12,13]))
print(binarySearch(6, [2,4,6,12,13]))
print(binarySearch(12, [2,4,6,12,13]))
print(binarySearch(13, [2,4,6,12,13]))

## Output:
# None
# 0
# 0
# 1
# 2
# 3
# 0
# 1
# 2
# 3
# 4
```

Does anyone have any tests I haven’t thought of?

312. Given the blog owner’s choice of Lisp language, I’m surprised that of the first ~300 entries, mine was the only Scheme one. Wow! :-) (I just grepped for “(define”, so someone correct me if I missed something.)

313. Bevan

Ruby – NON Recursive

So perhaps it doesn’t count having written once already… but I wrote a new one, avoided the syntax errors that caught me up the first time, realized that recursion is going to eat a lot of unnecessary resources for large arrays, and ran correctly out of the box this time. :)

```def binsort(target,sorted_array)
@left = 0;
@right = sorted_array.length - 1
@result = -1
while (@result<0)
@range = @right - @left
if (@range<0)
break
end
@index = @left + ((@range%2==0) ? @range/2 : (@range+1)/2)
if (target==sorted_array[@index])
@result = @index
elsif (target>sorted_array[@index])
@left = @index+1
else
@right = @index-1
end
end
return @result
end
```

It’s interesting that all the common error cases (null array, element missing) get caught by the same test for @range being negative.

314. slumgullion

Untested, un-peeked (except for the non-overflowing mid calculation which was in one of the first solutions). I already know it doesn’t do the empty array test so, I fail it but, let hope the rest works…

```int binary_search(int target, int* ints, unsigned n)
{
// check range first (too dumb to try to incorporate it into the main algorithm)
if (target < ints[0] or ints[n-1] < target) {
return -1;
}

// hi is one-past-end
for (int lo = 0, hi = n; lo < hi; ) {
// yah bug I read that blog post recently
//      int mid = (lo + hi) / 2;
// correction that I cheated and looked at
int mid = lo + (hi - lo) / 2;
int found = ints[mid];

if (target < found) {
hi = found;
}
else if (found < target) {
lo = found;
}
else {
return mid;
}
}
// failure
return -1;
}

```
315. Heimy

Err… forgot to post the couple last lines :P

```        else:
print "ERROR:  %d in %s?" % (needle, haystack)
```
316. Forgot to account for a search for a non-existent element; so I failed :(

```function binSearch(\$A,\$value) {
\$range = \$idx = ceil(count(\$A) / 2);
while (\$range > 0) {
if (\$A[\$range] == \$value) return \$range;
\$idx = ceil(\$idx / 2);
if (\$A[\$range] < \$value) {
\$range += \$idx;
} else {
\$range -= \$idx;
}
}
return -1;
}
```
317. Works as far as I can tell…

```#!/Users/jsharpe/.rvm/rubies/ree-1.8.7-2010.01/bin/ruby

# \$ ./binary.rb 10
# \$ ./binary.rb 12
# 12

class Array
def bsearch(n)
if self.empty?
else
i = self.length / 2
midpoint = self[i]
if n == midpoint
return n
elsif n < midpoint
new_end = self.length == 1 ? -2 : i - 1
self[0 .. new_end].bsearch(n)
elsif n > midpoint
self[i + 1 .. -1].bsearch(n)
end
end
end
end

arr = Array(-500..500).map{|a| a * 3}

puts arr.bsearch(ARGV[0].to_i)
```
318. This is interesting, a somewhat related post can be found here:
The gist of this is that version of BSearch implemented in the JDK contained a bug due to an overflow error. I recall reading about it some time ago, funny to see it come up again.

[Mike says: this is, I think, the third comment point out the Josh Bloch integer-overflow article as though I hadn’t linked to it from the original post itself. I can only assume these are being posted by people who’ve not actually read my post. I’m letting them all through moderation because they’re not spam and not abusive, but they really don’t add much to the discussion.]

319. slumgullion

uy, lo,hi = found instead of mid; IFI. But other than that mine’s good. Bonus points for elegance I say; not a +/- 1 to be found :)

320. dhasenan

I didn’t read the challenge until I tested my code. I only made one change after testing, and that did not affect correctness. (I had a special case for arrays of length 1.)

It turns out I instinctively avoided a bug that would have resulted in an infinite loop when checking a slice containing two elements. Lucky, I say.

Also in D.

```int find_impl(T)(T[] arr, T val, size_t index)
{
if (arr.length == 0) return -1;
auto center = arr.length / 2;
if (arr[center] == val) return center + index;
if (arr[center] < val) return find_impl(arr[center + 1 .. \$], val, index + center + 1);
return find_impl(arr[0 .. center], val, index);
}

int find(T)(T[] arr, T val)
{
return find_impl(arr, val, 0);
}
```
321. Chris

First version had a bug in it, easily fixed though.

Looking through the comments I like the recursive solutions.

Does it mean you’re not a professional or decent programmer if your first version has a couple of bugs in it…? i don’t think so.

I’m not sure what this proves.

322. Martin

I think this is a bit of a sham. My guess is the author of the book is just overly picky when reviewing. My first run seg faulted :P but this was not a result of the function, but rather an argument reading error where I tried to read argv at argc instead of argc-1, so I don’t count that as my logic error as it was outside the bsearch function. All subsequent testing succeeded.

```int bs(int size, int *array, int needle)
{
int ub=size-1;
int lb=0;
int point=0;

while (lb!=ub)
{
point=(ub+lb)/2;
if (needle==array[point])
return (point);
else if (needle>array[point])
lb=point+1;
else if (needle<array[point])
ub=point-1;
}

if (array[lb]==needle)
return (lb);
else
return (-1);
}
```
323. Heimy

@Joe User (comment 1805): Applied my tests to your code and it failed in the first one, ie. looking for a value outside the range. Say you have a list [1, 3, 5, 7] and I look for 0… your code gets into an infinite loop

324. Kevin
```private static boolean search(int[] array, int start, int end, int t) {
if (end - start == 1) {
return array[start] == t || array[end] == t;
}
if (end == start) {
return (array[start] == t);
}
int middle = (end-start)/2+start;
middle++;
if (array[middle] == t) {
return true;
}
else if (array[middle]< t) {
return search(array, middle+1, end, t);
}
else {
return search(array, start, middle-1, t);
}
}
```

Works AFAIK

325. One last attempt to get word press to quit eating all my code :(

```import org.junit.Test;
import static org.junit.Assert.*;

public class BinarySearch {

public int binarySearch(int x, int[] array) {
int low = 0;
int high = array.length - 1;
int i = (high+low) / 2;

while (low < high && array[i] != x) {
if (array[i] > x) {
high = i - 1;
i = (high+low) / 2;
} else if  (array[i] < x) {
low = i + 1;
i = (high+low) / 2;
}
}

if (array[i] == x)
return i;
return -1;
}

@Test
public void test() {
int [] array = new int[] {0,1,2,3,4,5,6,7,8,9 };

for (int i = 0; i < array.length; i++) {
assertEquals(i, binarySearch(i, array));
}
assertEquals(-1, binarySearch(20, array));
assertEquals(-1, binarySearch(-20, array));
}
}
```
326. Martin

I know I just posted, but some of these implementations (assuming they passed testing) might be useful over at http://rosettacode.org/wiki/Binary_search if your language hasn’t been done yet.

Mine worked.

I created a binary tree (computing next node pointer during the search, not ahead of time). It uses recursion. It’s probably not the fastest, and with 3 classes it’s also the most lines that i’ve seen so far… but it works.

I did it in C++.

328. I failed, but I got it fixed in about 5 mins :)

329. veek

Test cases are key. My first implementation worked for all values in the list, and values that fell inside the range of the list (> than least, greatest and < least test cases popped into my head. Had to add another check for the latter. So, does it count as a fail if you yell "Done!" then realize you missed something?

330. Matchu

Ruby implementation came close. I’m pretty proud of that given that it was my first run ever, with no formal compsci training. Took three edits to match my big test suite :)

http://pastebin.org/160181

331. Matchu

Though the do-without-testing concept is interesting, I’m not really sure it accurately represents programming prowess. If an application is being correctly designed, automated testing while working should be encouraged.

I *could* have spent half an hour poring over the code, running test cases myself, but instead I just ran the test suite, found the problem, and identified and fixed it within a minute. Writing an algorithm in one’s head, pass/fail, seems like an interesting test, but it not the mark of a good, productive programmer.

Or maybe I’m just whining since my 5-minute attempt didn’t pass. Ah well.

332. Writing code without testing is akin to doing math without a calculator.

333. This seems to work – first attempt.

```# the list to be searched
data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

# what we're searching for
search = 7

found = False
# did we run out of data?
if len(data) == 0: break

# partition the list (take advantage of default integer division in 2.6)
p = len(data) / 2

# proceed based on data at partition
if data[p] == search:
found = True
break
elif data[p] > search:
data = data[:p]
else:
data = data[p+1:]

if found:
print "Found it!"
else:
```
334. Got mine working (as much as I can see, but that doesn’t say much…) after one quick bug in testing (instead the correct array position for the found (pos[mid]) i returned mid)… Any comments?

```def bsearch(inlist, item):
n = len(inlist)
if n == 0:
return None
pos = range(n)
while len(pos) > 0:
mid = int(len(pos) / 2.0)
test = inlist[pos[mid]]
if (test == item):
return pos[mid]
elif (test < item) and (mid  item) and (mid > 0):
pos = pos[0:mid]
else:
return None
return None
```
```[1]: mylist = ['a', 'b', 'c', 'd']
[2]: print bsearch(mylist, 'c')
> 2
```
335. Mark

It won’t pass the integer overflow test (though at least it will throw an exception rather than silently failing), but here’s my answer in Clojure:

```(defn binary-search
"Performs a binary search for a value v in a given sequence s.
Returns an index of the value if found, nil otherwise."

([s v a b]
(if (> a b)
nil
(let [m (floor (/ (+ a b) 2))
x (s m)]
(cond (= v x) m
(> v x) (recur s v (inc m) b)
(< v x) (recur s v a (dec m))))))

([s v]
(binary-search s v 0 (dec (count s)))))
```

So that’s my “vote” — if we were supposed to protect against integer overflow I didn’t get it, otherwise I did.

336. Jason C

“””
def bsearch(x, l):
print l
if len(l) == 1:
return x == l[0]
pivot = len(l)/2
val = l[pivot]
if x == val:
return True
elif x < val:
return bsearch(x, l[:pivot-1])
else:
return bsearch(x, l[pivot:])
"""

337. Matthias Goergens

Jonathan Deutsch, I can’t decide whether your comment is trite or deep.

Arithmetic without a calculator borders on nonsense. But for analysis, algebra or proofs in general, you’d need a very advanced calculator.

338. Carl

Succeeded (at least on my test cases), in M. I assume array is zero-indexed.

```find(array,val) new pos,delta,found
set delta=array,pos=array\2
for  set delta=delta\2 do  quit:found  quit:delta<1
. if pos>array set pos=pos-delta quit
. if pos<0 set pos=pos+delta quit
. if array(pos)>val set pos=pos-delta quit
. if array(pos)<val set pos=pos+delta quit
. if array(pos)=val set found=1 quit
quit \$select(found:pos,1:-1)
```

(It may be worth noting that the right way to do this in M would be to use the values as the subscripts to the array, since arrays in M are actually more of a map structure.)

339. Alex

Hmm. So the question now is, can we trust programmers to tell the truth about how good they are?

I think the answer is clearly no.

340. jerryjvl

Success under the specified conditions, but a slight failure in the enhancement I tried to make at the same time.

I tried to get the .NET semantics where the index is returned when the element is found, and the two’s complement of the index the element should have been otherwise. I rushed the two’s complement part and got the value slightly wrong, but the basic ‘is-it-there-or-not’ search was correct, including overflow safety provided my ‘a + ((b – a)/2)’ is the correct solution for a safe midpoint calculation… I didn’t have enough memory to determine whether there is a gotcha there ;)

341. Vilhelm S

Mine seems to work, at least for the handful of testcases I tried.

```char* search(char x, char a[], int n) {
if (n==0)
return NULL;

int mid = n/2;
if (x == a[mid])
return &a[mid];
else if (x < a[mid])
return search(x, a, mid);
else
return search(x, a+mid+1, n-mid-1);
}
```
342. Michael Schmahl

As requested, I report that I failed. I wrote

```if (array[test] > value) low = test+1;
```

When it should have been:

```if (value > array[test]) low = test+1;
```
343. ```class Array:
data = []
def __init__(self, arr=[]):
self.data = arr[:]

def search(self, e, start=0, end=None):
if end==None: end=len(self.data)

if end <= start: return None
if start < 0: return None               # really throw
if end > len(self.data): return None    # really throw

mid = start + (end-start)//2

if self.data[mid] == e: return mid
if self.data[mid] < e: return self.search(e, mid+1, end)
return self.search(e, start, mid)
```

Tested briefly, seems to work correctly. Assuming I can use the rule “You’re allowed to use your compiler to shake out mechanical bugs such as syntax errors or failure to initialise variables” to cover learning to write classes in Python (because it took me three tries to reference class variables correctly), it worked first try.

344. Wrote, tested, posted. Note that this is searching for a key-value pair with a given key.

```def search_helper(l, key, mini, maxi):
midi = (mini+maxi)/2
if midi == mini or midi == maxi:
return None
kv = l[midi]
if kv[0] == key:
return kv
elif kv[0] < key:
return search_helper(l,key,midi,maxi)
else:
return search_helper(l,key,mini,midi)

def bsearch(l,key):
return search_helper(l,key,-1,len(l))
```
345. Mihai

How about proving it correct before even testing? I’ve used VCC http://vcc.codeplex.com/

```#include <vcc.h>
#include <limits.h>

int bs(unsigned int len, int *a, int t)
requires (len >= 0)
requires (len < UINT_MAX/2)
requires (wrapped(as_array(a, len)))
requires (forall(int i; 0 < i && i < (int)len ==> forall (int j; 0 <= j && j < i ==> a[j] <= a[i])))
ensures (result >= 0 ==> a[result] == t)
ensures (result < 0 ==> forall(int i; 0 <= i && i < (int)len ==> a[i] != t))
{
unsigned int start = 0, end = len;
while (start < end)
invariant (end <= len)
invariant (forall(int i; 0 <= i && i < (int)start ==> a[i] < t))
invariant (forall (int i; (int)end <= i && i < (int)len ==> a[i] > t))
{
unsigned int m = (start + end) / 2;
if (a[m] < t) start = m + 1;
else if (a[m] > t) end = m;
else return (int)m;
}
return -1;
}
```
346. Matthew Todd

To say only 10% can write a binary search is inaccurate. The rules being applied here are not realistic and rather contradictory to some development processes. For example:

NO testing until done writing? What about Test Driven Development?

Do you actually expect programmers to be able to write completely bug free code on their first run through?

I understand the basic premise: that programmers seemingly aren’t as good as we’d expect. But this feels like another apocalyptic assessment of how “kids” these days can’t code worth a damn. Not to say that all the high level coding with libraries degrading overall competency isn’t a worry.

I should mention that I fall in the kid age group, as I’m still in college. But I’m nearing the teenage years regarding overall experience and intuition.

347. SF

To be honest I only tested it with one array, I spent most of my time making it small… I was hoping to get it in under 80 characters, but I’ve only managed 111.

`int b(int v,int d[],int l){int i,n=l>>=1;do{i=n;n=v<d[i]?i-l:v>d[i]?i+l:i;l>>=1;l=l?l:1;}while(n!=i);return i;}`
348. Got this wrong on the first try, didn’t handle failure to find the target item. Can’t find any other bugs but let me know if you do:

```function bsearch(arr, target) {
var rec = (function(s,e) {
if(s > e) return null;
var idx = Math.floor((e-s)/2) + s;
if(arr[idx] == target) {
return idx;
} else if(target < arr[idx]) {
return rec(s,idx-1);
} else {
return rec(idx+1, e);
}
});
return rec(0, arr.length-1);
}
```
349. Evan

In Go:

```func bsearch(s []int, t int) int {
var i int
for {
if len(s) == 0 {
return -1
}
i = len(s)/2
if s[i] == t {
return i
} else if s[i] > t {
s = s[0:i]
} else {
s = s[i+1:]
}
}
return -1
}
```
350. def bsearch(ar, v):
if len(ar)==0: return -1
if v ar[-1]: return -1
return bsint(ar, v, 0, len(ar))

def bsint(ar, v, f, t):
if f==t:
if ar[f]==v:
return f
else:
return -1
mid = (f+t)/2 # integer arithmetic
am = ar[mid]
if am==v: return mid
if vam: return bsint(ar, v, mid+1, t)

351. Daniel

Wrong the first time.

352. finsprings

Had less-than rather than less-than-or-equal-to as my loop-condition but other than that it worked in my tests.

```/*
* Returns index of element with value item if present, -1 otherwise.
*/
static int my_bsearch(const int *pArray, int size, int item)
{
int start_point = 0;
int end_point = size - 1;
int mid_point;

do
{
mid_point = start_point + ((end_point - start_point) / 2);

if (pArray[mid_point] == item)
{
return mid_point;
}
else if (pArray[mid_point] < item)
{
start_point = mid_point + 1;
}
else
{
end_point = mid_point - 1;
}
} while (start_point <= end_point);

return -1;
}
```
353. Correct after fixing two syntax errors:

```def binSearch(lst,value):
return binSearchR(lst,value,0,len(lst)-1)

def binSearchR(lst,value,minimum,maximum):
if maximum-minimum == 0:
if lst[maximum] == value:
return maximum
else:
return -1
middle = minimum+(maximum-minimum)/2
if lst[middle] == value:
return middle
elif lst[middle] > value:
return binSearchR(lst,value,minimum,middle-1)
else:
return binSearchR(lst,value,middle+1,maximum)

#testing...
print binSearch([0,2,4,6,8,10,11,14,29,35,46,98],35)
```
354. finsprings

forgot to mention that I forced myself to do it in C95 without recursion…because it had been a while.

355. A file of “standard” test cases

I’ve written a file of 4096 tests of the following form:

```Problem 1
3
in [
1
2
4
]? no

```

You can find zipped and gzipped versions of the file, a more detailed explanation, and Python code to test your Python function against the file, here.

I’m amazed how many people thought Mike’s point or Bentley’s point was about not testing code. Of course you should test! The point is whether you can get it right without using testing as a crutch to get there before you test.

356. `function s(\$n,\$h){\$f=0;\$l=count(\$h)-1;do{\$m=floor((\$l+\$f)/2);if(\$h[\$m]==\$n)return \$m;if(\$f==\$l)return;if(\$n&lt;\$h[\$m]){\$l=\$m-1;}else{\$f=\$m+1;}}while(\$f&lt;=\$l);}`

Developed and tested on the command line. I didn't get it right on the first run.

357. Emanuel Evans

Got it wrong the first time (it was a small fix)–here’s the corrected version:

```bsearch :: (Ord a) => a -> [a] -> Maybe a
bsearch _ [] = Nothing
bsearch a xs | a == x = Just x
| a < x  = bsearch a (fst halves)
| a > x  = bsearch a (drop 1 \$ snd halves) --didn't do "drop 1" on the first go around, which resulted in an infinite loop
where halves = splitAt i xs
x      = xs !! i
i      = length xs `div` 2
```
358. Mike J
```private int SearchBinary(int[] ArrayToSearch, int ToFind, int startpos, int endpos)
{
if ((endpos - startpos) == 0)
{
if (ArrayToSearch[endpos] == ToFind)
{ return endpos; }
else
{ return -1; }
}
// Testposition - roughly in the middle of endpos and startpos
int Testposition = (endpos+startpos)/2;
if (ArrayToSearch[Testposition] == ToFind)
{ return Testposition; }
else if (ToFind < ArrayToSearch[Testposition])
{ return SearchBinary(ArrayToSearch, ToFind, startpos, Testposition); }
else
{ return SearchBinary(ArrayToSearch, ToFind, Testposition, endpos); }
}
```
359. mkpenta

PHP bi_search – work for first test and every test after. should work for integers, floats, characters. No particular reason for language choice.

``` 2)
{
if(\$arr[\$half]  \$ele)
return bi_search(array_slice(\$arr,0,\$half),\$ele);
}
elseif(\$n == 2)
return (\$ele == \$arr[0] || \$ele == \$arr[1]);
else return (\$n == 1 && \$arr[0] == \$ele);

}
?>
```
360. Mike J

My above code has not been tested – C#.

361. Andrew C
```def binsearch( target, offset, alist):
if not alist:
return -1
midInd = len(alist)/2
midVal = alist[midInd]
if (midVal == target):
return offset + midInd
elif (midVal &lt; target):
return binsearch(target, offset+midInd+1, alist[midInd+1:])
else:
return binsearch(target, offset, alist[:midInd])
```

It seems to work, except I stupidly forgot the increment in the second case the first time I tried it.

362. Will Groppe

Argh, failed. 2 huge bugs. Shame upon me.

363. Langtree

A try:

```public class BinSearch {
public static final int binSearch(final int[] array, final int target) {
final int lowIndex = 0;
final int highOffset = array.length - 1;
final int middleOffset = highOffset >>> 1;

for (;;) {
final int middleIndex = lowIndex + middleOffset;
final int middleElement = array[middleIndex];
if (target == middleElement) return middleIndex;
else if (highOffset == 0) return -1;  // If lowIndex == highIndex and not found yet, not going to be found
else if (target < middleElement)
highOffset = middleOffset - 1;
else {
final int delta = middleOffset + 1;
lowIndex += delta;
highOffset -= delta;
}
middleOffset = highOffset >>> 1;
}
}
}
```
364. artsrc

Python not tested or compiled:

```
def find(a, l):
""" return the index of a in the sorted list l or None if it is not there """
start = 0
end = len(l) - 1
while start <= end:
mid = (start + end) / 2
if l[mid] == a:
return mid
elif a < l[mid]:
end = mid - 1
else:
start = mid + 1
return None

```
365. Pieces

I failed.

I would agree with several other posters that the implement without testing is a strange way to go about development. I could have found my problem if I sat and looked long enough, but instead I ran it, found the problem and fixed it in minutes. *shrug*

366. Mike J

Found 1 bug as I tested the code (infinite loop). I needed to change teh condition to be <= 1 and not == 0.

Time : roughly 2 hours.
Status: Failed – initial attempt
Working as of second attempt – not thoroughly tested.

```        /// <summary>
/// Binary Search
/// </summary>
/// <param name="ArrayToSearch">Array of ints</param>
/// <param name="ToFind">Integer to find</param>
/// <param name="startpos">Starting Position</param>
/// <param name="endpos">Ending position</param>
/// <returns>the position (zero base) if found otherwise -1</returns>
private int SearchBinary(int[] ArrayToSearch, int ToFind, int startpos, int endpos)
{
if ((endpos - startpos) <= 1)
{
if (ArrayToSearch[endpos] == ToFind)
{ return endpos; }
else if (ArrayToSearch[startpos] == ToFind)
{ return startpos; }
else
{ return -1; }
}
// Testposition - roughly in the middle of endpos and startpos
int Testposition = startpos + (endpos - startpos) / 2;
if (ArrayToSearch[Testposition] == ToFind)
{ return Testposition; }
else if (ToFind < ArrayToSearch[Testposition])
{ return SearchBinary(ArrayToSearch, ToFind, startpos, Testposition); }
else
{ return SearchBinary(ArrayToSearch, ToFind, Testposition, endpos); }
}
```
367. Andrew Crawford

So I wrote my binary search in Perl and it worked at first go, just like it will for so many other readers of your blog. I doubt anyone’s day will be enhanced by me posting the code, so please take my word for it.

I think the reason why only circa 10% of programmers can write a functioning binary search routine is that only circa 10% of programmers have brains wired for implementing low-level algorithms.

Twenty years ago, “not being able to write low-level algorithms” was the same as saying “not able to program computers” but the past few decades of progress in software development have been aimed specifically at allowing the other 90% – the ones who can’t actually program – to produce useful software despite their handicap. This has been great for the 90%, and for the companies who employ them, but it’s come at a cost to programming culture.

368. DanielKeep

I actually wrote two implementations. The first was a completely naive recursion version, which worked perfectly.

The second was an iterative version of the first, but I made a stupid, horrible mistake. When I’d finished, I decided that my extra slice variable was redundant and I could just mutate the original array.

This wouldn’t have been a problem except that I’d chosen the sentinel value for “not in array” to be the length of the array as opposed to -1. Since I was now mutating the original array, my iterative version would always return index 0 for any element not in the array. WHOOPSIE.

That’ll teach me to try and be clever.

On the upside, I was pleasantly surprised when all the assertion failures for the recursive method turned out to be bugs in the tests.

Also on the up side is that neither function should be susceptible to the overflow bug by virtue of using D’s slicing syntax.

369. DanielKeep

On another note, I think discounting the overflow bug is a bad idea: it’s a bug, end of story. It’s not hard to avoid, given the correct data structure (in this case, slices eliminate it entirely).

370. Luke

I did a unit test. Sorry.

```int binarySearch(vector<int> array, int num) {
int max = array.size();
int min = 0;
int middle = floor(max/2.0);
int prevMid;

do {
prevMid=middle;
int val = array[middle];
if      ( val > num ) {
max = middle;
}
else if ( val < num ) {
min = middle;
} else { return middle;}
middle = min + (floor(max-min)/2.0);
}  while (prevMid != middle) ;
return -1;

}
```
371. I failed. I wrote the code (below) and ran through 5 simple test cases but it wouldn’t find the element if it was the last in the list.

I thought this was a great exercise. I haven’t used System.arrayCopy in forever, and 50% of my job is J2EE development!

```	public static boolean bsearch(int[] a, int s) {
if(a.length == 1) {
if (a[0] == s) {
return true;
} else {
return false;
}
} else if(a.length == 2) {
if (a[0] == s) {
return true;
} else {
return bsearch(new int[] {a[1]}, s);
}
} else {
int midpoint = a.length / 2;
if(a[midpoint] == s) {
return true;
} else if(a[midpoint] < s) {
int[] upperHalf = new int[(a.length-1)-midpoint];
System.arraycopy(a, midpoint, upperHalf, 0, (a.length-1)-midpoint);
return bsearch(upperHalf, s);
} else {
int[] lowerHalf = new int[midpoint];
System.arraycopy(a, 0, lowerHalf, 0, midpoint);
return bsearch(lowerHalf, s);
}
}
}
```
372. Langtree

Ahh, shouldn’t have made those three variables final and fixed my failure returns.

Now it should be guaranteed not to overflow and to work properly.

```public class BinSearch {
public static final int binSearch(final int[] array, final int target) {
int lowIndex = 0;
int highOffset = array.length - 1;
int middleOffset = highOffset >>> 1;

for (;;) {
final int middleIndex = lowIndex + middleOffset;
final int middleElement = array[middleIndex];
if (target == middleElement) return middleIndex;
else if (target < middleElement) {
if (middleOffset == 0) return -1;
highOffset = middleOffset - 1;
}
else {
if (middleOffset == highOffset) return -1;
final int delta = middleOffset + 1;
lowIndex += delta;
highOffset -= delta;
}
middleOffset = highOffset >>> 1;
}
}
}
```
373. Kaleberg

This sounds like a lot of fun, but it’s sort of a party novelty. Are you allowed to use backspace to delete, or is it a one shot: write it and release it? I don’t know if I could avoid hitting backspace. It’s rather horribly ingrained by now.

I don’t really see the point of writing code without testing. The whole point of programming is to write broken code and fix it. Usually I just create an empty source file and start debugging. That’s one of the reasons I like Realbasic. You create an empty program and run it, and up comes a trivial window and a menu with the quit command. It’s a very satisfying starting point, full of possibilities. Then I pop open a text editor and start the spec.

After all, the last few times I’ve written a binary search were to find an insertion point, not a particular element, and to search a very large, but relatively uniform database by estimating a “mid” point based on the extreme and search values. A old working binary search I had lying around made an excellent starting point. Just replace the axe blade, slip in a new handle, try a different blade, and voila, it’s all debugged.

374. Marcus
```def search(array, value):
oldIndex = 0
leftBound = 0
rightBound = len(array)
while True:
index = leftBound + (rightBound - leftBound) / 2
if(array[index] == value):
return index
elif(array[index] > value):
rightBound = index
else:
leftBound = index
if(index == oldIndex):
return
oldIndex = index
```
375. doh! it should’ve been:

```else if(a[midpoint] < s) {
int[] upperHalf = new int[(a.length-1)-midpoint];
System.arraycopy(a, midpoint+1, upperHalf, 0, (a.length-1)-midpoint);
return bsearch(upperHalf, s);
}

```
376. Mark Ransom

I’m going for extra credit here, posting my Python code before I test it. This isn’t the first time I’ve written a binary search, but it’s been a long time – at least 15 years as best as I can remember. I long ago learned the secret – make sure each pass is narrowing the search range by at least 1, otherwise you can get into an infinite loop.

To make this more interesting, I made it work with only a less-than operator, similar to the way the standard C++ library works.

I’m quite surprised that you didn’t include some test conditions, but I see a few comments above mine that at least one person has volunteered. Thanks!

```def binary_search(sorted_seq, target):
bottom = 0
top = len(sorted_seq) - 1
while top >= bottom:
mid = (top + bottom) / 2
if target < sorted_seq[mid]:
top = mid - 1
elif sorted_seq[mid] < target:
bottom = mid + 1
else:
return mid
return None
```
377. Lutz Mueller
```
def bsearch(arr,val,b=0,e=arr.length-1)
# trivial cases
return false if arr.empty?
if(e-b<2)
# one or two elements
return b if(arr[b]==val)
return e if(arr[e]==val)
return false
end
# recursive case
pivot = ((b+e)/2).floor
return pivot if arr[pivot]==val
return bsearch(arr,val,b,pivot-1) if arr[pivot]>val
return bsearch(arr,val,pivot+1,e)
end
```
378. ```int mybsearch(const int arr[],const int length,const int target){
int start=0,end=length-1;
int index = (start+end)/2;
int found = 0;

while(start<end){
if(arr[index]==target){
found = 1;
break;
}
if(arr[index]<target)
start=index;
else if(arr[index]>target)
end=index;
index=(start+end)/2;
if(index==start){
if(arr[index]==target)
found=1;
else if(arr[++index]==target)
found=1;
break;
}
}
if(found)
return index;
return -1;
}
```

Alrighty then, what are the test cases?

379. Lutz Mueller

grr, how do I edit this again?

above source is what I ended up with (Ruby). I failed insofar as one of my test cases produced an endless recursion. I then decided to handle the trivial cases explicitly, with good results.

380. cycojesus

gist.github.com/371995

381. emusln

Failed on initial try in C with conditional silliness, took a couple more “oh, yeah, that” thoughts to finish.

382. Hippopotenuse

Am one of the 90% – didn’t consider zero length input array. I’m ashamed to say I wrote it in IDL.

383. I didn’t have the stones to post it without trying it out but I did write it all the way before I did. If I’d have been in the class, I’d have been part of the 10%. Woo Hoo!

```<?

for (\$i=0; \$i<100; \$i++){
\$array[\$i]=\$i*10;
}

\$desiredNumber=3000;

\$found=false;
\$maxIndex=count(\$array)-1;
\$minIndex=0;
\$trialIndex=floor(\$maxIndex/2);

do {

if (\$array[\$maxIndex]==\$desiredNumber){
echo "it's at \$maxIndex<BR>";
break;
}
elseif (\$array[\$minIndex]==\$desiredNumber){
echo "it's at \$minIndex<BR>";
break;
}
elseif (\$array[\$minIndex]<\$desiredNumber and \$desiredNumber<=\$array[\$trialIndex]){
echo "it might be between \$minIndex and \$trialIndex<BR>";
\$maxIndex=\$trialIndex;
}
elseif (\$array[\$trialIndex]<=\$desiredNumber and \$desiredNumber<\$array[\$maxIndex]){
echo "it might be between \$trialIndex and \$maxIndex<BR>";
\$minIndex=\$trialIndex;
}
else{
echo "it's outside of the range of values in the array<BR>";
break;
}

if (\$maxIndex-\$minIndex<=1){
echo "there is no element with that value<BR>";
break;
}

\$trialIndex=floor((\$maxIndex-\$minIndex)/2)+\$minIndex;

}
while (\$found!=true);
```
384. Ok crap, my code fails if the array has a length of 1. Need to use

`start<=end`

`start<end`

as the while condition. FAIL.

385. DB

Ugly and inelegant, but it works. I hope.
Seems to, anyways.

Running:

```% while (true); do rv=`./bs | grep "Found" | sed -e 's/.*in //'`; echo "1" >> \$rv.bs; done
^C

% wc -l *.bs
789 10.bs
1650 11.bs
3351 12.bs
5122 13.bs
2647 14.bs
264 7.bs
399 8.bs
394 9.bs
14616 total

% more bs.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

int binsear (int *, int, int, int *);

int compare_int (const void *a, const void *b) {

const int *da = (const int *)a;
const int *db = (const int *)b;

return (*da > *db) - (*da < *db);
}

int main (int argc, char *argv[]) {

int values[100];

int t,sv,sr,i,itr;

for(i=0;i<100;i++) {
values[i]=rand()%10000;
}

qsort(values, 100, sizeof(int), compare_int);

sr=time(NULL);
srand(sr);
t=rand()%100;
sv=values[t];

printf("rand: %d \n T value: %d [%d]\n",sr,sv, t);

printf("Found %d @ [%d]",sv, binsear(values,100,sv,&itr));
printf(" in %d\n",itr);
return 0;
}

int binsear(int *values,int size, int sv, int *itr) {

int *sptr,*bptr,*tptr;
int cval,*cptr;
int cind=0;

sptr=bptr=values;
tptr=values+(size);
cval=-1;

*itr=0;
while (sv != cval) {

(*itr)++;
cind+=(tptr-bptr)/2;
cptr=sptr+cind;
cval=*cptr;

if(cval == sv) {
return(cind);
}

if(sv > cval) {
bptr=cptr++;
} else {
cind-=(tptr-bptr)/2;
tptr=cptr--;
}
if (bptr==tptr || (cptr > sptr+size || cptr < sptr)) {
printf("Error: %p %p %p %d %d\n",bptr,tptr,cptr,*cptr,sv);
exit(2);
}
}

return cind;
}
```
386. Success! I wrote a recursive version first:

struct array_elem
{
int key;
char *value;
};

char *bin_search(struct array_elem *array, int count, int key)
{
if (count==0)
{
return NULL;
}
else
{
int split_ix = count/2;
int split_value = array[split_ix].key;
if (split_value \> key)
{
return bin_search(array, split_ix, key);
}
else if (split_value \ key)
{
count = split_ix;
}
else if (split_value \< key)
{
array += split_ix + 1;
count -= split_ix + 1;
}
else
{
return array[split_ix].value;
}
}
}
}

Both work on the handful of test cases I've tried, so there might be some bugs. I'm curious what the common mistakes are.

387. I take it back. I misses some values with the floor() calculation. Bummer.

388. caf

I’m going to own up to a failure on the first attempt.

I started writing it after reading the Programming Pearls quote rather than later in the article, so I didn’t see the “no testing” admonition until later.

For posterity:

```int binsearch(int a[], int nelem, int val)
{
int i = 0, j = nelem - 1;

while (i < j)
{
int k = (i + j) / 2;

if (a[k] < val)
i = k + 1;
else
j = k;
}

if (a[i] == val)
return i;
else
return -1;
}
```
389. tyoook

I got syntax errors on my first try, but after I cleaned them up the code passed my tests:

```<?php

function array_bsearch(\$val, array \$sorted_array)
{
\$length = count(\$sorted_array);
if (\$length == 0) return FALSE;

\$mid = \$length/2;
\$mid_val = \$sorted_array[\$mid];

if (\$val == \$mid_val) return \$mid;

\$half_array = (\$val < \$mid_val)?
array_slice(\$sorted_array, 0, \$mid):
array_slice(\$sorted_array, \$mid + 1);

return array_bsearch(\$val, \$half_array);
}

?>```
390. nicholas

My code worked the first time, but my test had a bug. (When the haystack had duplicates, it would want bsearch to magically give back the correct one.)

```def bsearch(arr, elem):
begin = 0
end = len(arr)

while begin < end:
if begin == end - 1:
if arr[begin] == elem: return begin
else: return None
mid = (begin + end) / 2

if elem < arr[mid]: end = mid
else: begin = mid

import random

random.seed(hash("good news everybody"))

for i in xrange(1000):
n = random.randrange(10, 100)
numbers = [random.randrange(0, 100) for _ in xrange(n)]
numbers.sort()

for index in xrange(len(numbers)):
result = bsearch(numbers, numbers[index])
if numbers[index] != numbers[result]:
print 'Oh noes! %d vs %d (looking for %d in %r)'  %\
(index, result, numbers[index], numbers)

not_here = numbers[index] + 1
if not_here not in numbers:
result = bsearch(numbers, not_here)
if result:
print "I taught I saw a putty tat (%d) at %d, but I didn't (%r)" %\
(not_here, result, numbers)
```
391. jayfo
```def bsearch(the_list, the_val):
if len(the_list) == 0:
return False

left = 0
right = len(the_list)-1
middle = (left+right)/2

while left != right:
if right-left == 1:
return (the_list[left] == the_val) or (the_list[right] == the_val)
elif the_val == the_list[middle]:
return True
elif the_val < the_list[middle]:
right = middle
else:
left = middle
middle = (left+right)/2

return the_list[left] == the_val
```
392. James

I had no trouble implementing a correct solution, although sample arrays to test with probably would be nice

393. finsprings

doh, meant C89 not C95

394. Here’s my attempt, with associated tests:

```def bsearch(thing, the_list):
"""A binary search to find thing in the_list.

assert the_list == sorted(the_list)
if the_list == []:
return None

middle = len(the_list) // 2
print thing, "vs.", middle, the_list

if the_list[middle] == thing:
return middle
elif the_list[middle] > thing:
return bsearch(thing, the_list[:middle])
else:
result = bsearch(thing, the_list[middle+1:])
if result is not None:
return middle + 1 + result
else:
return None

print bsearch(0, range(10))
print bsearch(4, range(10))
print bsearch(9, range(10))
print bsearch(10, range(10))
```

I had two bugs (so far). The first was that I got the middle comparison around the wrong way, and the second was that I forgot to add 1 to the final result. I might have a go at an iterative version later on…

395. sean

I failed. Though I ended up with a correct implementation, I went and coded it before I saw the “no testing” rule, and my code was not correct for my first test.

396. cdsmith

Here’s my Haskell solution, at least a bit different than others posted so far:

```import Data.Array

binarySearch :: (Ord e, Ix i, Integral i) => Array i e -> e -> Maybe i
binarySearch arr x = let (a,z) = bounds arr in go a z
where go lo hi | lo > hi         = Nothing
| (arr!mid) == x  = Just mid
| (arr!mid) < x   = go (mid + 1) hi
| otherwise       = go lo (mid - 1)
where mid = (lo + hi) `div` 2
```
397. imazesoul

So, here’s my 1 hour JS tryout. It’s not tested so hopefully I nailed it!

```function bsearch (ar, T) {
var l = 0
, m
, u = ar.length;

do{
m = Math.floor( l+(u-l)/2 );

if( T === ar[m] ){ return true; }

T > ar[m] ? l = m+1 // Lower is inclusive
: u = m;  // upper is not
}while(u > l);

return false;
}
```
398. David McCammond-Watts

I used Delphi

```// Returns the index of Item in Arr or -1 if not found
function BinarySearch(const Arr: array of Integer; Item: Integer): Integer;
var
Left, Right: Integer;
begin
Left := 0;
Right := High(Arr);
while Left <= Right do begin
Result := (Left + Right) div 2;
if Item < Arr[Result] then
Right := Result - 1
else if Item > Arr[Result] then
Left := Result + 1
else
Exit;
end;
Result := -1;
end;
```
399. Seems my last comment was truncated, here a new try:

``` #!/usr/bin/env ruby def rec_binsearch( tab, search, min, max ) if min > max return -1 end med=(max + min)/2 if tab[med] == search return med end if tab[med] =0 puts %{tab[#{res}]=#{tab[res]}} else puts %{can't find #{search} in [#{tab.join(' ')}]} end ```

400. programmer barbie

I failed. Programming is hard, let’s go shopping!

401. Finally I protected my ‘<‘ by HTML code…

```#!/usr/bin/env ruby

def rec_binsearch( tab, search, min, max )
if min > max
return -1
end
med=(max + min)/2
if tab[med] == search
return med
end
if tab[med] < search
min=med+1
else
max=med-1
end
return rec_binsearch( tab, search, min, max )
end

def binsearch( tab, search )
min=0
max=tab.length
return rec_binsearch(tab,search,0,tab.length-1)
end

search=ARGV[0].to_i
tab=ARGV[1..-1].map{ |x| x.to_i }
res=binsearch(tab,search)
if res>=0
puts %{tab[#{res}]=#{tab[res]}}
else
puts %{can't find #{search} in [#{tab.join(' ')}]}
end
```
402. In ruby, in the spirit of Bently’s code description:

```a = [1,2,3,5,6,7,8,9,11]
sought = 4
found = false
range = a.size
base = 0
while range > 0 && !found
mid = range / 2 + base
lower_range = upper_range = range / 2
upper_range -= 1 if range.even?
if a[mid] == sought
found = true
elsif a[mid] < sought
base = mid + 1
range = upper_range
else
range = lower_range
end
end
puts "found: #{found}"
```

I had to mentally test this before getting the upper and lower range calculation correct.

@Kaleberg: “An old working binary search I had lying around made an excellent starting point.” – agree, usually I find this to be a superb strategy!

403. An iterative version. I had a bit more trouble with this one, it went into a spin and I had to limit the number of iterations:

```MAX_ITER = 10

def bsearch(thing, the_list):
"""A binary search to find thing in the_list.
iters = 0
assert the_list == sorted(the_list)

low = 0
high = len(the_list)

print thing, the_list
while 1:
iters += 1
if iters > MAX_ITER:
return "Aargh!"

mid = (low+high) // 2
mid_value = the_list[mid]
print low, mid, high

if low == high:
return None
if mid_value == thing:
return thing
elif mid_value > thing:
high = mid
else:
low = mid

print bsearch(0, range(10))
print bsearch(4, range(10))
print bsearch(9, range(10))
print bsearch(10, range(10))
```

I had a number of bugs in this one, which took a while to work out. The first was that I (again!) had my comparison around the wrong way, and the second is that I’m not sure that there’s a clean way to prevent my code going into an infinite loop for non-existent values. I have an off-by-one error in there, perhaps?

Yep, so I’m a terrible programmer – I’ll go hang my head in shame now… but read up on binary sort :)

404. Jeremy Holman

Many commenters have said that this challenge is meaningless, since there is no real-world application of coding without testing. I disagree.

First, I have found that practicing coding on paper forced me to learn better habits about correctness, which results in higher coding speed. So [if you’re like me], doing drills of this non-interactive nature will improve your productivity.

Second, frankly, if you can’t manage this elementary a case (without tests), how can you trust yourself to come up with all the relevant tests? Consider those who posted their allegedly-tested programs and were incorrect. There but for the grace of formal proof methods go I.

Oh, and I wrote it in 10 or 15 minutes, recursively in Python, and believe it to be error-free. Let’s see if I can post it successfully:

```def binser2(t,a,begin,end):
if begin == end: return False
mid = (begin+end) / 2
if a[mid] == t: return mid
if t < a[mid]: return binser2(t,a,begin,mid)
return binser2(t,a,mid+1,end)

def binser(t,a):  # t is the target, a is the array
return binser2(t,a,0,len(a))
```
405. Nick

Success. I just want to point out that this is a really terrible problem. Given the rules, it is not surprising that 90% fail, and it is not really a measure of programmer skill or productivity.

```int bs(int* array, int count, int value) {
int min = 0;
int max = count;
while (min < max) {
int mid = (max + min) / 2;
if (array[mid] == value)
return mid;
else if (array[mid] > value)
max = mid;
else
min = mid + 1;
}
return -1;
}```

I could have written this, debugged it, and written a battery of unit tests in five minutes. Instead it took me about 25 minutes of being a human compiler/computer before I was confident enough to compile and run it. I used pen and paper to test it by hand and clean out the bugs. This is what I have a problem with; I could have just used the computer to do this for me. I found this problem incredibly frustrating because I was stripped of everything that I consider makes me a good programmer.

Here’s the test I ran against it in case anyone was wondering. Not terribly thorough, but I really don’t care.

```int test[] = {1, 3, 4, 7, 9, 10, 11, 17, 18, 19, 25, 26, 29, 30};

int main(void) {
int count = sizeof(test) / sizeof(int);
for (int i = 0; i < 35; ++i)
printf("searching %i: position %i\n", i, bs(test, count, i));
return 0;
}```

All values in the output matched up with their position in the array. I also had no compiler errors or warnings in the implementation of bs() on first compile (as C99); I got an error first because gcc compiles in C89 by default (so it complained about the for loop declaration), and I got a warning because I forgot to include stdio.h (technically part of the test, since the algorithm does not need that header.)

406. Erik Swanson

I believe this is correct. No promises though, I’m a novice coder.

```#!/usr/bin/python

def half(length):
return int(length*.5)

def search(array,T):
range = [half(len(array)), 0, len(array)]
value = array[range[0]-1]
while value != T:
if value > T:
range[2] = range[0]
place = 0
elif value < T:
range[1] = range[0]
place = 1
range[0] = half(range[0]) + place*range[0]
value = array[range[0]-1]
return range[0]
```
407. Shaun

Language this month=Actionscript 3.

```public function binarySearch(array, val):int
{
return binarySearchHelper(array, val, 0, array.length);
}

public function binarySearchHelper(array, soughtValue, startIndex, endIndex):int
{
trace((startIndex +" "+ endIndex));
if(startIndex >= endIndex)
return -1;

var halfway:int = Math.floor((endIndex+startIndex)/2);

if(array[halfway] == soughtValue)
return halfway;

if(array[halfway] > soughtValue)
{
return binarySearchHelper(array, soughtValue, startIndex, halfway);
}
return binarySearchHelper(array, soughtValue, halfway, endIndex);
}
```

Did not work the first try, as I had mixed up my . (This is the fixed version.)

408. Shaun

Woops, that was supposed to be: “Did not work the first try, as I had mixed up my less-than and greater-than signs”

409. Nick

Oh also, I should mention I tested mine on paper for (almost) all branches for array sizes zero through five (yes, this is why I am frustrated.) So I am confident that it is correct.

I still don’t think these rules are fair. For instance my code obviously fails integer overflow, as others have mentioned in their own code. Does this even matter? I wouldn’t expect an algorithm of bs() to guard against this in any way besides an assert(). I don’t consider this an error.

I find it silly that putting – instead of +, for example (as I did in (min + max) / 2, luckily I noticed it before compiling) is considered failure, which is something that would immediately be caught if we were allowed to test; and yet, people here are claiming success with recursive solutions in languages without tail-call optimization, so they have O(log n) space requirements (the algorithm should be O(1) memory.)

This can’t possibly be graded pass/fail. A question like this on a paper test makes sense if you can still get part marks for a decent attempt.

Anyway. /complaining

410. Michael Shaw

Failed on first attempt, forgot to exclude the middle element in the recursive call:

def bsearch(in_list, target):
if len(in_list) == 0:
return False
else:
middle_index = len(in_list) / 2
middle = in_list[middle_index]
if middle == target:
return True
elif middle LESSTHAN target:
return bsearch(in_list[middle_index + 1:], target)
else:
return bsearch(in_list[:middle_index], target)

411. Not tested yet. Thirty minutes. Revolution, written recursively, which glancing at some of the other solutions I’m not sure I prefer now. I wrote it to take a list rather than an array.

```function bSearch k,pList,pOffset
-- k, value to find
-- pList, the (sorted) list to search
-- pOffset, where the current list starts relative to the start of the original list
-- returns the index of of k in pList
-- call with pOffset empty
if pOffset is empty then put 0 into pOffset -- FYI, Revolution uses 1-based lists
put (1 + the number of items of pList) div 2 into tMidPoint -- 4 = 2, 5 = 3, 6 = 3, 7 = 4, etc.
put item tMidPoint of pList into tMidValue
switch
case tMidValue < k -- k is in the top half if at all
return bSearch(k,(item tMidPoint + 1 to -1 of pList),(pOffset + tMidPoint))
case tMidValue > k -- k is in the bottom half if at all
return bSearch(k,(item 1 to tMidPoint - 1 of pList),pOffset)
case tMidValue = k -- found it!
return pOffset + tMidPoint
default
end switch
end bSearch
```
412. Not quite clean.

```#!/usr/bin/env ruby

class BinarySearch

def initialize(sorted_items, target)
@items = sorted_items || []
@target = target
end

def run
if target and items.size > 0
search(0, items.size - 1)
else
false
end
end

private
def search(index_first, index_last)
# termination conditions

# only one left
if index_first == index_last
# match?
if target == items[index_first]
return true
else
return false
end
end

# never found. index of the first is the larger than the last
return false if index_first > index_last

# never found. target is smaller than first item
return false if items[index_first] > target

# never found. target is larger than last item
return false if items[index_last] < target

# recusive
# division, index_first..index_mid, index_mid + 1..index_last
index_mid = (index_last + index_first) / 2  # it is floor in integer division

# in first half?
if search(index_first, index_mid)
return true
# in second half?
elsif search(index_mid + 1, index_last)
return true
else
return false
end
end
end

if ARGV.size >= 0
items = (ARGV[1..-1] || []).sort
target = ARGV[0]

puts "Items : [#{items.join(",")}]"
puts "Target: #{target}"
puts "--"
else
puts "Usage: bs <target> <list of items>"
end

```
413. David Foster

Got it right the first time.

```public class Search {
public static void main(String[] args) {
int[] a = new int[] {2,4,6};
System.out.println(binarySearch(a, 7));
}

static int binarySearch(int[] a, int n) {
int min = 0;
int max = a.length - 1;

while (min <= max) {
int mid = (min + max)/2;

int value = a[mid];
if (value == n) {
return mid;
} else if (value < n) {
min = mid + 1;
} else if (value > n) {
max = mid - 1;
}
}
return -(min+1);	// insertion point for non-found element
}
}
```

There are a few reasons why this algorithm is tricky.

* If you use a lim-index instead of a max-index, you’re likely to access outside the buffer when searching for an element higher than the array max. Fencepost error.

* It’s easy to forget the case of searching for a non-existent element. In the case above, I’ve even provided a return value that tells you (unambiguously) where the insertion point would be for a non-existent element.

414. Five minutes, and Python, obviously:

def binary_search(collection, value):
“””returns the index”””
if not collection:
return None
if collection[0] == value:
return 0
if collection[0] > value:
return None
if collection[-1] == value:
return len(collection) -1
if collection[-1] < value:
return None

# Bisect:
mid = len(collection) // 2
if mid == 0:
# Done:
return 0
if collection[mid] == value:
return mid
if collection[mid] value:
return binary_search(collection[:mid], value)

Seems to work, although I have only made like three tests. :) I find the idea of a challenge where you aren’t allowed to actually run your code moronic. This isn’t testing for how good programmers are, it’s more about luck, IMO. I’d say the passage in the book is outdated, because now we have something called test-driven development. :)

415. Followup: seems to work. Tested:
1. target is in list
2. target is at start of list
3. target is at end of list
4. target is not in list
5. target is less than smallest value in list
6. target is greater than largest value in list
7. target is empty
8. list is empty
9. target and list are empty

416. Kristof

sure not the fastest but kinda readable for me:

```def find(array, what)
return what == array[0] if array.size == 1

mid = array.size/2

lower = array[0..mid-1]
higher = array[mid..array.size]

result = find(lower, what)
result = find(higher, what) unless result

result
end

a = [1,2,4,6,7,10]

(0..10).each do |x|
puts x if find(a, x)
end
```
417. @dewb:
> Testing is part of software development. This challenge is a bit like asking artists to draw a perfect circle while blindfolded. It’s a neat parlor trick, but you can’t use it as a litmus test for a “real artist” or “real programmer.”

My daughter went to art school, and one of the exercises they used was to draw something without ever looking at the paper. So perhaps your analogy is more confirming than refuting.

418. JEIhrig
```//C program written in comment window, no compile check.
// Tab character is saved to clipboard.
int search(int *list, int high, int low, int key)
{
int mid;
mid = (low + high) / 2;
if (high == low)
{
return key;
}
else if (key  list[mid])
{
return search(list, mid + 1, high, key);
}
}
```
419. JEIhrig

How are you going to test all these!? I see just about every programming language imaginable here!

420. Alex Ungur

Just a small rewrite of my previous version (shortened the variables’ names to 1-2 letters to see how short can it get :D) + unit testing to ensure that it works as designed. Looks like it does:

```def search(x, a, m = a.size / 2)
return nil if x < a.first or x > a.last
return x if x.eql?(a[m])
search x, a[m] > x ? a[0,m] : a[m..-1]
end

if \$PROGRAM_NAME.eql?(__FILE__)
require 'test/unit'
class TestSearch < Test::Unit::TestCase
MaxVal      = 1000
SearchSpace = Array.new(MaxVal / 2){rand MaxVal}.uniq.sort.freeze

def test_must_find_all_values_that_exist_in_search_space
SearchSpace.each {|x| assert_equal x, search(x, SearchSpace)}
end

def test_must_return_nil_for_values_not_found_in_search_space
((0...MaxVal).to_a - SearchSpace).each {|x| assert_nil search(x, SearchSpace)}
end
end
end
```
421. Following the prototype of C99 bsearch():
, I wrote this:

http://pastebin.com/i8UGMkJi

Lots of room for improvements, but meh. I’m going to steal other people’s tests now and check it out.

422. This was actually the first time I ever implemented the binary search. And I actually think I got it right, too!

Source code in PHP follows. Wrote some basic tests too, but don’t want to waste space.

```# non-recursive binary search
function bs( \$needle, \$a )
{
\$start = 0;
\$end = count( \$a ) - 1;

while( \$start < \$end ) {
# middle is relative to start
\$mid = \$start + ceil( (\$end - \$start) / 2 );
if( \$needle > \$a[\$mid] ) {
\$start = \$mid + 1;
} else if( \$needle < \$a[\$mid] ) {
\$end = \$mid - 1;
} else {
# lucky shot!
\$start = \$end = \$mid;
}
}

# \$start = \$end now, which might be a match .. or not.
if( \$needle == \$a[\$start] ) {
return \$start;
} else {
return false;
}
}
```
423. Untested Javascript. (A bit bold since I’m new to the language.)

```// Return an i such that array[i] === key if possible, else null.
// Pre: array is sorted ascending.
function search(array, key) {
for (var lo = 0, hi = array.length; lo < hi; ) {
// Inv: 0 <= lo < hi <= array.length
// Inv: key is in [lo..hi) if anywhere
// Termination counter: hi - lo
var mid = lo + ((hi - lo) >> 1);
if (array[mid] < key)
lo = mid + 1;  // hi'-lo' = hi-mid-1 = hi-lo-((hi-lo)>>1)-1
else if (array[mid] === key)
return mid;
else
hi = mid;      // hi'-lo' = mid-lo = (hi-lo)>>1
}
return null;
}```
424. Anon

Apparently Adobe have found similar results. Years ago Sean Parent posted that they used the test on interview candidates and saw high failure rates. The only article I can find now is http://stlab.adobe.com/wiki/images/8/8c/Boostcon_possible_future.pdf (warning – this document contains a binary search implementation).

425. ```#!/usr/bin/env python

from math import log
from random import randint

random_array = sorted(list(set([randint(0, x) for x in range(20000)])))

def binary_search(R, T):
iteration = 1
N = len(R)
middle = R[N / 2]
print 'Searching %s item array for %s' % (N, T)

while(T != middle):
if len(R) == 1:
return
iteration += 1

if T < middle:
R = R[:len(R)/ 2]
else:
R = R[len(R) / 2:]

middle = R[len(R) / 2]
print 'Found %s on iteration #%s' % (T, iteration)

if __name__ == '__main__':
binary_search(random_array, randint(0, len(random_array)))
```
426. Figo

Not tested:

```int bs(int *array, int value, int first, int last){
if(last - first <= 1){
if(array[first] == value){
return first;
}
else if(array[last] == value){
return last;
}
else {
return -1;
}
}
else {
int new_first, new_last, fulcrum;

fulcrum = (first + last)/2;

if(array[fulcrum] >= value){
new_first = first;
new_last = fulcrum, first;
}
else {
new_first = fulcrum + 1;
new_last = last;
}

return bs(array, value, new_fist, new_last);
}
}
```
427. alk509

My first try failed. I had to switch my first two if-statements around and now it (looks like it) works:

int bsearch(int* haystack, int left, int right, int needle) {
int middle = (right + left)/2;

if (haystack[middle] == needle) {
return middle;
}
if (left >= right) {
return -1;
}
if (haystack[middle] > needle) {
return bsearch(haystack, left, middle, needle);
}
if (haystack[middle] < needle) {
return bsearch(haystack, middle+1, right, needle);
}
}

428. Alright, it actually looks correct. Tried out of range values as well as valid ones, empty array as well as a huge one, and I confirmed the results with a debugger, just in case.

Now, here are some bugs that 20 minutes of thinking solved (without testing!):

* When computing the middle index, avoid additions. They might overflow for large arrays. I’ve learned that in the past, the HARD way.
* Testing for (!found) usually leads to infinite loops, so I ditched that approach quickly.
* I started writing a binary sort…then I decided to read the specifications! :-)
* Although this is a typical example of a recursive algorithm, I’m not comfortable enough with recursion (I know, shame on me…), so I decided to go iterative..
* Do not mix semantics. If you decide your binary_search() should return an index into the array, this will impact your implementation – using uints instead of plain ints for example, which may or may not lead to nasty bugs if you’re not careful.

429. Omar

Full disclosure:

You shouldn’t probably include me in the statistics, because I did test my code a good amount of times. But I only tried it because I was doing the binary search in Haskell, but I’ve only been playing with Haskell for a few days, and with limited time, so I am far from truly getting it.

That being said, after a few times, i got this:

```binSearch2 :: [Int] -> Int -> Bool
binSearch2 list number
| (null list) = False
| ((getMiddleValue list) == number) =
True
| ((getMiddleValue list) > number) =
binSearch2 (fst (splitInHalf list)) number
| otherwise =
binSearch2 (snd (splitInHalf list)) number

getMiddleValue :: [Int] -> Int
getMiddleValue list
| ((length list) == 1) = list !! 0
| otherwise = (last (fst(splitInHalf list)))

splitInHalf :: [Int] -> ([Int],[Int])
splitInHalf list = (splitAt (div (length list) 2) list)
```

Like I said before, I’ve only been playing with Haskell for a few days, but it seems to work. Probably not the best way to do it, and maybe I didn’t even exactly follow the binarySearch algorithm (I think I did…did I?), but thats what I came up with.

Hope you guys like it :D

430. dan

``` int binsrch(int count, int *integers, int n) { int mid; int *ptr = integers;```

``` while (count > 0) { mid = count / 2; if (ptr[mid] == n) { return mid + (ptr - integers); } if (ptr[mid] < n) { ptr = ptr + mid + 1; count -= mid + 1; } else { count = mid; } } ```

``` return -1; } ```

431. @Kragen Javier Sitaker: nope it won’t, BUT it isn’t correct either:

```var a = new Array(2);
document.write("result (should be 0): " + bsearch(a, 2, 0, a.length));
```

That case fails. So I’m not in the 10%, shame on me! :)

432. Romy

Yup, overlooked a silly bug in mine, fail++

433. Dmitri Arkhipov

Python, not tested

```def bSearch(sortedList, T):
if( len(sortedList) == 1 ):
if(sortedList[0] == T):
return True
else:
return False
else:
middleIndex = int( (len(sortedList)/2) )
return ( bSearch(sortedList[:middleIndex], T) or bSearch(sortedList[middleIndex:], T))
```

Addendum: as a recent Compsci Grad I am contractually obligated to know nothing and fail consistently. Therefore all errors found here-in are intentional and are to be commended thoroughly .

434. Anon

Doh, fails when the search item is not in the container. To my defense, it’s 4:30 in the morning and I’m going to sleep now.

Note to self: if you get up at 4 in the morning to get a drink of water, check the time on your laptop and see that someone sent you a link to a blog post, ignore it until morning.

```import random

l = set()
for _ in xrange(500):

l = sorted(l)
pin = random.choice(l)

print "Looking for", pin, "in", l
left, right = 0, len(l)-1
iters = 0

while l[left] != pin:
iters += 1
half = (right - left) / 2
if pin > l[left + half]:
left += half
elif pin < l[left + half]:
right -= half
else:
print "Found at position", left + half, "after", iters, "iterations"
break

print "All done"
```
435. Robert Leffmann

Plain C code, worked at first try though I did test it before submitting here, which took some time before I realized that while the binary search was working, my small test code was faulty.

```int binsearch(int value, int *array, int size)
{
int start = 0, end = size-1;

while(end >= start)
{
int index = (start+end)/2;

if(array[index] == value)
return index;

if(value < array[index])
end = index-1;
else
start = index+1;
}

return -1;
}
```
436. Helge

5 minutes to write, another minute to fix syntax errors; untested

```/* -1: not found, otherwise array index */

ssize_t bin_search(int array[], size_t size, int key)
{
size_t low = 0, high = size;
while(low < high) {
size_t middle = (low + high) >> 1;
if (key == array[middle]) return middle;
if (key < array[middle]) high = middle;
else /* key > array[middle] */ low = middle + 1;
}

return -1;
}
```

after reading the description further and encountering the part about “index overflow”, I was banging my head on the table as I fell in exactly that trap :/ for “integers” it does not matter, but for “chars”, it would

437. ```int BinarySearch(int *arr, int arrSize, int findThis)
{
if (arr == NULL || arrSize > 1);

if ((minIndex >= arrSize ||
maxIndex  findThis)
maxIndex = poolIndex - 1;
else if (arr[poolIndex] < findThis)
minIndex = poolIndex + 1;
}

return -1;
}
```
438. Robert Leffmann

I just saw you have more than 400 replies to this entry, and you only posted last night!

Why do you think your blog has exploded in popularity? The catchy title, the uncooked fish (sorry I had to) or the witty writing?

I think the results of this experiment will come out differently than the 10% success rate mentioned. Telling people to only post anonymously so they can’t receive shame nor credit for their code would have been better.

With the amount of readers you have on your blog, you could conduct some pretty interesting experiments.

439. Ramesh

I have used the same prototype of bsearch. Didn’t test it.

```#include <stdio.h>
#include <stdint.h>
#include <errno.h>

typedef int (*compare_func_t) (void *, void *);
extern int errno;

static compare_func_t  compare_func;
static int compare_elem_size = 0;

void * bin_search(void * a, void * look_for, int start, int end)
{
int mid, ret;
char * input = a, *output = NULL;
unsigned long long offset;

if (start > end) {
return NULL;
}
mid = (end - start)/2 + start;
offset = mid * compare_elem_size;
ret = compare_func(&input[offset], look_for);

if (ret < 0) {
return bin_search(a, look_for, start, mid - 1);
} else if (ret > 0) {
return bin_search(a, look_for, mid + 1, end);
}
output = &(input[offset]);
return (void *)output;
}

void * binary_search(void * a, void * look_for,
int (*cmp_func)(void *, void *), int size, int num_elem)
{
if (num_elem <= 0 || num_elem > INT32_MAX) {
errno = -EINVAL;
return NULL;
}
if (cmp_func == NULL || size == 0) {
errno = -EINVAL;
return NULL;
}
compare_func      = cmp_func;
compare_elem_size = size;
return bin_search(a, look_for, 0, num_elem -1);
}
```
440. Figo

After testing it looks good.

I tested with random values wich resulted in arrays with repeated values. That is something I didn’t have in mind when wrining the code. It turns out my function returns the first of the repeated values, which is nice. Lucky me :)

The code (again) and the random test:

```#include <time.h>
#include <stdlib.h>
#include <stdio.h>

int bs(int *array, int value, int first, int last){
if(last - first <= 1){
if(array[first] == value){
return first;
}
else if(array[last] == value){
return last;
}
else {
return -1;
}
}
else {
int new_first, new_last, fulcrum;

fulcrum = (first + last)/2;

if(array[fulcrum] >= value){
new_first = first;
new_last = fulcrum, first;
}
else {
new_first = fulcrum + 1;
new_last = last;
}
return bs(array, value, new_first, new_last);
}
}

int compar(const void *a, const void *b){
if(*(int*)a < *(int*)b)
return -1;
if(*(int*)a > *(int*)b)
return 1;
return 0;
}

#define ARR_SIZE 10
#define MAX_RND 15
int main(){
int array[ARR_SIZE];
int i, value, ret;

srandom(time(NULL));
for(i=0;i<ARR_SIZE;i++){
array[i] = random() % MAX_RND;
}
qsort(array, ARR_SIZE, sizeof(int), compar);

printf("       ");
for(i=0;i<ARR_SIZE;i++){
printf("%2d ",i);
}
printf("\nArray: ");
for(i=0;i<ARR_SIZE;i++){
printf("%2d ",array[i]);
}
printf("\n");

for(i=0;i<15;i++){
value = random() % MAX_RND;
printf("value: %d, position: %d\n", value, bs(array, value, 0, ARR_SIZE-1));
}
}
```
441. Written in Redcode. :-) Worked first time but I did a couple of test cases on paper while I was coding. Is that cheating?

442. Antti
```#include <iterator> // std::iterator_traits

// binsearch: Expects two random-access iterators which denote a sorted half-open range [begin, end), the item being searched for, and a comparator that is a strict weak ordering on T
template <typename Iter, typename T, typename Comp>
Iter binsearch(Iter begin, Iter end, T item, Comp comp, Iter nil) {
typename std::iterator_traits<Iter>::difference_type length = end - begin;
Iter mid = begin + length / 2;
switch(length) {
case 0:
return nil;
case 1:
if(!comp(item, *mid) && !comp(*mid, item))
return mid;
else
return nil;
default:
if(comp(item, *mid))
return binsearch(begin, mid, item, comp, nil);
else
return binsearch(mid, end, item, comp, nil);
}
}

template <typename Iter, typename T, typename Comp>
Iter binsearch(Iter begin, Iter end, T item, Comp comp = Comp()) {
return binsearch(begin, end, item, comp, end);
}
```

Compiled, but not tested.

443. Did it in about 30 minutes while watching TV. As far as I know, it’s bug-free.

```import sys
input = [1,2,4,5,6]
T = 4 if len(sys.argv) == 1 else int(sys.argv[1])
print "T = %s" % (T,)
start, end = 0, len(input)-1
while start != end:
mid = start + int(round((float(end) - start)/2))
if input[mid] > T:
end = mid - 1
else:
start = mid
if input[start] == T:
print start
else:
```
444. joost

forgot to put the source-meta stuff in, now ok. I tested meanwhile and know I belong to the 90%.

```; return list starting after <start> end ending at <end>
(defun sublist (lst start end)
(butlast
(nthcdr start lst)
(- (length lst) end)
)
)

; find key key in list lst
(defun binsearch( key lst )
(let ((middle (/ (length lst) 2))
)
(progn
(if (< key (nth middle lst))
(binsearch key (sublist lst 0 middle ))
(if (> key (nth middle lst))
(binsearch key (sublist lst middle (length lst)))
(if (equal key (nth middle lst))
key
nil)
)
)
)
)
)

```
445. Andrew Molyneux

I thought I’d give it a crack in C#.
Disclaimer 1: I’m pretty good in C and C++ but I have no serious experience with C#.
Disclaimer 2: I’ve walked myself through this code in my head but I haven’t tested it.

The BinarySearch() function returns the index of the item if found, otherwise -1.

```static long BinarySearch(int[] array, int item)
{
long first = 0;
long last = array.Length - 1;
while (first <= last)
{
long index = first + (last - first) / 2;
if (array[index] == item)
{
return index;
}
if (array[index] > item)
{
last = index - 1;
}
if (array[index] < item)
{
first = index + 1;
}
}
return -1;
}
```
446. YBY

I failed. My version ends up in an infinite loop if the value I’m searching for is larger than all values in the array, or if there are only two values in the array and the searched-for value is between those two.

```import sys, math

val = int(sys.argv[1])
data = map(int, sys.argv[2:])

print "Searching for %s in %s" % (val, data)

def bsearch(v, l, m):
#import pdb; pdb.set_trace()
if(len(l) == 0):
return
p = int(math.floor(len(l) / 2))
b = l[p]
if(v == b):
return p + m
if(v > b):
return bsearch(v, l[p:], m + p)
return bsearch(v, l[:p], m)

print "Result: %s" % bsearch(val, data, 0)
```
447. Andrew Molyneux

Having tested my code, it seems to be correct as far as I can tell. The only thing I missed is the possibility that the array reference passed can be null. I’d treat that as a precondition, so I’d insert the following line at the start of the function:

```Debug.Assert(array != null);
```
448. poulejapon

no check…

I’m gonna test it after posting.
I’m pretty scared of the result though.

{source}
def binary_search(x,v):
def aux(a,b):
if a==b:
return a if v[a]==x else None
else:
p = (a+b+1)/2
if v[p]>x:
return aux(a,p)
else:
return aux(p,b)
return aux(0,len(v))
{/source}

449. Daniel Binau

I’m kind of a n00b who only knows how to “paste libraries together” in C#, so it was fun to do this exercise and feel like a real programmer :-D

I had two errors in my original attempt, both of which were easy to correct when I ran a simple test.

It is probably not a very elegant implementation, but it seems to work.

```public static int? SearchSortedArray(int[] ary, int n)
{
return SearchSortedArray(ary, n, 0, ary.Length - 1);  // Original error: Forgot to subtract 1 from ary.Length
}

private static int? SearchSortedArray(int[] ary, int n, int fromIndex, int toIndex)
{
if (fromIndex < 0 || toIndex >= ary.Length)
{
return null;
}

if (fromIndex == toIndex)
{
if (ary[fromIndex] == n)
{
return fromIndex;
}
else
{
return null;
}
}

int mid = (int)(fromIndex + toIndex) / 2 - (1/2); // Original error: Subtracted 1 instead of (1/2), resulting in an endless loop when toIndex - fromIndex == 2

int test = ary[mid];

if (test > n)
{
return SearchSortedArray(ary, n, fromIndex, mid - 1);
}
if (test < n)
{
return SearchSortedArray(ary, n, mid + 1, toIndex);
}

return (int?)mid;
}
```
450. André Silva
```

public class binarySearch {

public static int binary_search(int[] array, int element) {

return binary_search(0, array.length, array, element);
}

public static int binary_search(int lower_bound, int upper_bound, int[] array, int element) {

int middle = (upper_bound + lower_bound) / 2;

if(lower_bound == middle || upper_bound == middle)
return -1;

if(array[middle] < element)
return binary_search(middle, upper_bound, array, element);
else if(array[middle] > element)
return binary_search(lower_bound, middle, array, element);
else if(array[middle] == element)
return middle;

else return -1;
}

public static void main(String[] args) {

int array[] = {1,2,3,4,5,6,7,8,9,10};
int element = 0;

int position = binary_search(array, element);

System.out.println("Element " + element + " is at position " + position);
}
}
```
451. Well, I first written it (10-20 minutes) and then read till end where you say “do not test”.

I know myself, I make a lot of mistakes. So I always write software with help of testing and debugging.

For this task, testing was enough, I did not use debugger.

Warning! Super-ugly c# code below (written it in linqpad)

var testArr = new int []{1,2,2,3,3,3,3,5};

var found=false;
var findVal=5;
var endPos=testArr.Length;
var startPos=0;
int center=-1;
if (testArr.Length >0)
do {
var prevCenter=center;
center=startPos+(endPos-startPos)/2;
var curVal=testArr[center];
if (curVal==findVal) {
break;
}
if (prevCenter==center){
center=-1;
break;
}
if (curVal findVal){
endPos=center;
}

}
while (!found);

(center).Dump();

452. mishu

Scheme version, did no changes after testing it.

(define (bsearch item vec)
(define (iter start end)
(if (> start end)
-1 ; search failed
(let* ((middle (quotient (+ start end) 2))
(mid-val (vector-ref vec middle)))
(cond ((= item mid-val) middle)
((< item mid-val) (iter start (- middle 1)))
(else (iter (+ middle 1) end))))))
(iter 0 (- (vector-length vec) 1)))

453. Walter Stevens
```public class BSearch {

public static int search(int[] sortedArray, int target) {
return search(sortedArray, target, sortedArray.length/2, sortedArray.length, 0);
}

private static int search(int[] sortedArray, int target, int current, int high, int low) {
if (sortedArray[current] == target)
return current;
if (sortedArray[current] > target) { //Too high, cut out the top half
if (current > low)
return search(sortedArray, target, goDown(current, low), current, low);
return -1;
}

if (sortedArray[current] < target) { //Too low, cut out the bottom half
if (current < high)
return search(sortedArray, target, goUp(current, high), high, current);
return -1;
}

return -1;
}

private static int goUp(int current, int high) {
int goUpTo = ((current+high)/2);
if (goUpTo == current)
return current++;
return goUpTo;
}

private static int goDown(int current, int low) {
int goDownTo = ((current+low)/2);
if (goDownTo == current)
return current--;
return goDownTo;
}
}
```
454. David Mihola

As far as I can see, this seems to work. Written according to the rules.

```import java.lang.Math;

public class BinarySearchTest
{
public static void main(String[] args)
{
int[] a = {0};
System.out.println(bsearch(a, 1));

a = new int[] {0};
System.out.println(bsearch(a, 0));

a = new int[] {0, 1};
System.out.println(bsearch(a, 1));

a = new int[] {0, 1};
System.out.println(bsearch(a, 0));

a = new int[] {0, 1, 2, 3, 4};
System.out.println(bsearch(a, 3));

a =  new int[] {0, 1, 2, 3, 4};
System.out.println(bsearch(a, 5));
}

public static int bsearch(int[] a, int key)
{
int first = 0;
int last = a.length - 1;

int middle;

int foundAt = -1;

while (first <= last)
{
middle = (first + last) / 2;

if (key < a[middle])
{
last = middle - 1;
}
else if (key > a[middle])
{
first = middle + 1;
}
else if (key == a[middle])
{
foundAt = middle;
first = last + 1;
}
else
{
System.out.println("Error!");
}

}

return foundAt;

}
}
```
455. Daniel Binau

I tested the code I posted earlier. Searching an array of all the numbers between 0 and 100 million that are divisible by 3 only takes a couple of seconds and gives the correct result.

If I increase that number to 1 billion then I get memory overflow. This could of course be fixed by making it non-recursive but I’m too lazy for that :-)

456. Just for kicks, I ran through the first 100 comments or so and tallied the language choice:

Python 40
C/C++ 36
Unknown/pseudocode 6
Lisp/Clojure/Scheme 5
PHP 4
Three each: Java, Perl, C#, JavaScript
One each: VB, Delphi, Smalltalk, FORTRAN, Lua, Objective-C, ColdFusion

Conclusion: Almost everyone (who cares about implementing binary search, anyway) uses C/C++ or Python.

BTW, Google had me do this in my phone interview (reading code over the phone = not fun). I made the same off-by-one error as several commenters (< instead of <=) but caught it a few minutes later while we were still on the phone.

457. Avi

I *think* my first version works:

```int binSearch(int[] arr, int n) {
int first = 0;
int last = arr.length - 1;
while (first <= last) {
//int mid = first/2 + last/2 + (((first % 2 != 0) && (last % 2 != 0)) ? 1 : 0); // This is the correct version, but more complicated
int mid = (first + last) / 2; // This is the simplified version, but doesn't work for very large numbers
int found = arr[mid];
if (found == n) {
return mid;
} else if (found < n) {
first = mid + 1;
} else { // found > n
last = mid - 1;
}
}
return -1;
}
```
458. Failed… just. :-)

Firstly, I coded an inelegant recursive solution, and only when I started writing the test cases I realised I forgot the case of an empty array and a null array.

For valid sorted arrays, however, it worked just fine, including searching for an item not in the array (returning -1).

459. Jacul

I made three mistakes.Here is my orginal code.
{source}

public class A{

public static void main(){

search(7);
search(40);

}

public boolean search(final int n){
int[] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
int middle;
int left=0;
int right=a.length-1;
for(;leftmiddle){
left = middleindex+1;
}else {
right= middleindex-1;
}
}
return false;
}
}
{source}
As you can see,main() function didn’t take paraments; forgot to make search() function static; and middleindex should be (right+left)/2, that was a clerical error.
Please let me know if any other bug exists.

460. luxifer

I literally jumped in writing that code right when I read “try it” :-D

I ended up with this and it seems to work

```function binSearch(\$sterm, \$array) {
sort(\$array);
\$result = 0;
while(true) {
if(count(\$array)<=0)
return false;
\$j = round(count(\$array)/2)-1;
\$tmp = array(\$sterm, \$array[\$j]);
sort(\$tmp);
if(\$tmp[0] == \$tmp[1]) {
\$result += \$j;
return \$result;
} else if(\$sterm == \$tmp[0]) {
array_splice(\$array, \$j, count(\$array)-\$j);
} else {
array_splice(\$array, 0, \$j+1);
\$result += \$j+1;
}
}
}
```

basically it quite mimics array_search() but without implementing it’s \$strict parameter

461. Jacul

damn it! again:
{source}

public class A{

public static void main(){

search(7);
search(40);

}

public boolean search(final int n){
int[] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
int middle;
int left=0;
int right=a.length-1;
for(;leftmiddle){
left = middleindex+1;
}else {
right= middleindex-1;
}
}
return false;
}
}
{/source}

462. joost

this one works fine; second try though, elisp by the way

```; return list starting after <start> end ending at <end>
(defun sublist (lst start end)
(butlast
(nthcdr start lst)
(- (length lst) end)
)
)
; find key key in list lst
(defun binsearch( key lst )
(let ((middle (/ (length lst) 2))
)
(progn
(if (not (equal lst nil))
(if (< key (nth middle lst))
(binsearch key (sublist lst 0 middle ))
(if (> key (nth middle lst))
(binsearch key (sublist lst middle (length lst)))
(if (equal key (nth middle lst))
key
nil)
)
)
nil)
)
)
)

```
463. EoghanM

Python, success, I definitely thought about it a lot harder when I couldn’t test.

def binary_search(array, elem):
l, r = 0, len(array)-1
while True:
m = l + ((r-l)//2)
if array[m] == elem:
return True
elif r == l:
return False
elif array[m] > elem:
r = m
else:
l = m + 1

464. Pingback: 你是那10%可以写出二分查找的程序员吗？ » 为之漫笔

465. I can’t resist posing the evil question: if your array can be in size up to Integer.MAX_VALUE (for Java, but applies elsewhere as well), are you sure your code will not create integer overflows in your arithmetic? The code is only correct if it works for any arbitrary array being passed in…

466. David Mihola

@Martin Probst:

You are obviously right. Count me in with the 90% then…

but @Avi:

I think your correct solution is unnecessarily complicated; someone else further up wrote something like this:

middle = first + ( (last – first) / 2);

This should also avoid the problem of integer overflows, shouldn’t it?

467. luxifer

@Martin Probst: at least mine shouldn’t
@EoghanM: shouldn’t you return the position instead of just “yeah, found it in there”? :-)

468. Tristan

whoops, fell into the wordpress markup trap! Once again…

```function binarySearch(array, target) { //20, 19
var length = array.length;
var start = 1;
var end = length;
while(start <= array.length && start <= end) {
if(target == array[end-1]) {
return end-1;
} else if (target == array[start-1]) {
return start-1;
}
if(target > array[end-1]) {
start = end + 1;
end += Math.round(length/2);
} else { // target < array[end]
end -= Math.round(length/2);
}
length = end - start + 1;
}
}
```
469. komu

My code was correct.

470. Here’s mine (recursive in Objective-C): http://gist.github.com/372377

I haven’t found any errors in my casual testing.

471. Antti

Oh and here’s how you might test my earlier C++ binsearch:

```#include <vector>
#include <iostream>
#include <functional> // std::less
#include <algorithm> // std::sort
#include <ctime> // std::time
#include <cstdlib> // std::rand, std::srand

int main() {
std::vector<int> v;
std::srand(std::time(0));
for(int i = 0; i < 20; ++i)
v.push_back(std::rand() % 60);

std::sort(v.begin(), v.end());

int val;

while(std::cout << "Enter value (any non-numeric input to quit): ", std::cin >> val) {
std::vector<int>::iterator iter = binsearch(v.begin(), v.end(), val, std::less<int>());
if(iter == v.end()) {
std::cout << "Value (" << val << ") not found!" << std::endl;
}
else {
std::cout << "Found value (" << val << ") at index " << iter - v.begin() << "." << std::endl;
}
}

char const* c = "[";
for(std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
std::cout << c << *i;
c = ", ";
}
std::cout << "]" << std::endl;
}
```

This methodology comes from (or rather, where I learned it from is) the C++ standard algorithms library, which is well worth examining because it has stellar design notwithstanding the ugliness of the language itself. The basic principles are applicable in most languages.

472. dawid joubert

Tested it, worked well for finding values but blew up trying to find value 200.

```#!/usr/local/bin/perl

use strict;

my @data = qw(1 2 5 6 7 9 10 13 19 20 200);
my \$left_index = 0;
my \$right_index = \$#data;
my \$target = 200;

LOOP:
if (\$left_index - \$right_index == 0) {
goto NOT_FOUND;
}

my \$index = (\$left_index+\$right_index) / 2;
my \$mid = \$data[\$index];

print "Grabbed value \$mid at index \$index\n";

if (\$mid == \$target) {
goto FOUND;
}

if (\$mid < \$target) {
\$left_index = \$index;
}

if (\$mid > \$target) {
\$right_index = \$index;
}

goto LOOP;

die "WTF Fall through";

FOUND:
die "The target has been found\n";

NOT_FOUND:
die "The target has not been found\n";

```
473. I failed, with a simple and easily found error, but I did it when I read “try it” in the quoted section, not your later challenge. So I assumed that testing was allowed, and stopped to do so early. Trying to write perfect code straight out of the blue seems pretty pointless. Some people even say you should write thorough tests first and then code until they pass. The scope of this example is about as big as you can get and hope to have any success just doing it all in your brain, so what’s the point?

474. JoshP

Works for my test cases first try. I know it’s a bit ugly but no one said write elegant or pretty code.

```int bsearch(int * arr, int len, int val)
{
int start = 0, end = len-1;

if(arr == 0 || len < 1)
{
return -1;
}
else if(len == 1)
{
if(arr[0] == val)
{
return 0;
}
else
{
return -1;
}
}

do
{
int mid = start + (end - start)/2;

if(mid == start)
{
if(arr[start] == val)
{
return start;
}
else if(arr[end] == val)
{
return end;
}
else
{
return -1;
}
}

if(mid > end || mid < start)
{
return -1;
}
else if(arr[mid] == val)
{
return mid;
}
else if(arr[mid] > val)
{
end = mid;
}
else
{
start = mid;
}
}while(start != end);

return -1;
}

```
475. Mark

I failed. That is all.

476. Jamie

First pass, buggy. Tried to be smart and got the sort condition backwards. Added one comprehensive test, fixed the bug. search(array, e)==i for all e=array[i] in a random, sorted array.

That said, coding without tests is just trouble waiting to happen. Doing so is part of my standard work routine, and explicitly specifying “no tests” pushes this firmly into the realm of theoretical uselessness, even for a random exercise.

477. Shawn
```
This was done in matlab

array=[1:.5:100];
T=0;
[m,lenA]=size(array);
pos=floor(lenA/2);
ubound=lenA;
lbound=array(1);

S=input('What to search for?: ');

while (T==0)
if (S>array(pos))
lbound=pos;
pos=lbound+abs(floor((ubound-pos)/2));
elseif (S<array(pos))
ubound=pos;
pos=abs(ceil((pos-lbound)/2));
end

if (S==array(pos))
T=array(pos);
break;
end

lbound;
ubound;
pos;

if (abs(lbound-pos)<=1)||(abs(ubound-pos)<=1)
T=-1;
break
end
end

if T==-1
else
fprintf('S was found at location %i in the array', pos);
end

```
478. 9 minutes

use warnings;
use strict;
use POSIX qw(floor);

use Test::More qw(no_plan);

sub bsearch {
my (\$list, \$target) = @_;

return unless @\$list;

my \$middle_index = floor(\$#\$list / 2);
my \$middle_val = \$list->[\$middle_index];

if (\$middle_val == \$target) {
return \$middle_val;
}
elsif (\$middle_val < \$target) {
return bsearch([@\$list[\$middle_index + 1 .. \$#\$list]], \$target)
}
else {
return bsearch([@\$list[0 .. \$middle_index – 1]], \$target)
}
}

for (1..10) {
ok(bsearch([1 .. 10], \$_))
}

ok(!bsearch([1 .. 10], 0));
ok(!bsearch([1 .. 10], 11));

479. Shawn

on my code, i wrote it to only work for integers, it could be modified to work for floats too

also, i got it on probably my 4th or 5th run-through when debugging

480. Dan

I didn’t get it quite right on the first go because of a stupid mistake – in the elif/else brackets, I’d originally just written “binsearch(…)” instead of “return binsearch(…)”. Other than that it appears to work.

```# unoptimized
def binsearch(lst, val):
if len(lst) == 1:
if lst[0] == val:
return True
else:
return False

mid = len(lst)/2
if lst[mid] == val:
return True
elif val < lst[mid]:
return binsearch(lst[:mid], val)     else:
return binsearch(lst[mid:], val)
```
481. Wow, from a quick audit it seems that mis-handling empty arrays is by far the most common mistake. Eg from a sampling of the solutions stated to be correct, I found it in 8 solutions (@finsprings, @Aaron, @Mike J, @Langtree, @Luke, @Marcus, @cycojesus, @Erik Swanson), with only 1 having a different mistake (@donaq, which was caught later).

482. Rodney

Success first time with Python.

def binSearch( array, item ):
low = 0
high = len(array)
while (high>low):
mp = (high+low)/2
if (array[mp].key == item): break
if (array[mp].key low):
return array[mp]
return None

483. Great work, Eric! I thought we might see a bit more of people pointing out bugs in each others’ code, but it’s nice to see that you weren’t satisified with destruction-testing just one solution :-)

And, hey, the rest of you — you’re not going to take this lying down, are you? :-) Can someone find a bug in Eric’s submission? It’s at
reprog.wordpress.com/2010/04/19/are-you-one-of-the-10-percent/#comment-1869

484. Joe SixPacks
```my \$SearchFor = 5;

my @List = (1,2,3,4,5,6,7,8,9,10);
my \$LowRange = 1 - 1;
my \$HighRange = 10 - 1;

my \$Index = -1;

while ((\$HighRange - \$LowRange) > 1)
{
my \$MidRange = \$LowRange + int((\$HighRange - \$LowRange) * 0.5);

if (\$List[\$LowRange] == \$SearchFor)
{
\$Index = \$LowRange;
last;
}
elsif (\$List[\$HighRange] == \$SearchFor)
{
\$Index = \$HighRange;
last;
}
elsif (\$List[\$MidRange] == \$SearchFor)
{
\$Index = \$MidRange;
last;
}
elsif (\$List[\$MidRange] > \$SearchFor)
{
\$HighRange = \$MidRange;
}
else
{
\$LowRange = \$MidRange;
}
}

if (\$Index == -1)
{
if (\$List[\$LowRange] == \$SearchFor)
{
\$Index = \$LowRange;
}
elsif (\$List[\$HighRange] == \$SearchFor)
{
\$Index = \$HighRange;
}
}

if (\$Index != -1)
{
print "\n\$List[\$Index] is in \$Index\n";
}
else
{
}
```
485. Rodney

Ok – that code didn’t paste correctly – lost indentation and lost middle part of text.

```def binSearch( array, item ):
low = 0
high = len(array)
while (high>low):
mp = (high+low)/2
if (array[mp].key == item): break
if (array[mp].key low):
return array[mp]
return None
```
486. woomoon

{source}
/**
* if success,return the index of [toFind] in [_data]
* else return -1.
* @param _data source data
* @param low start index of source data
* @param high end index of source data
* @param toFind number to find
* @return
*/
public static int search(int[] _data, int low, int high, int toFind){
if(_data == null){
return -1;
}
if(low > high){
return -1;
}
if(low >= _data.length || high >= _data.length){
return -1;
}
int mid = (low + high)/2;
if(_data[mid] == toFind){
return mid;
}else if(_data[mid] > toFind){
mid = mid – 1;
return search(_data, low, mid, toFind);
}else{
mid = mid + 1;
return search(_data, mid, high, toFind);
}
}
{source}
Only work for integers.
Write by using JAVA.
the potential bug may be found.

487. I did this in ruby, and my first code was not correct. I had an infinite loop because I was not shrinking the size of my window.

That said, the entire thing was coded, tested, corrected in less than 10 minutes, so I guess this is also a repeat of the “why is it important to be right first, as long as you are right at the end”. Testing is important for code.

488. Jeff

python:

def bsearch(needle, haystack) :
idx = len(haystack) / 2

if idx == 0 :
return -1

if needle == haystack[idx] :
return idx

if needle haystack[idx] :
return bsearch(needle, haystack[idx+1:]

success! i think. it may lose in an edge case (like haystack of length 0) but that’s outside the scope of the algorithm and more an exercise in defensive programming IMO.

489. ```def bsearch(needle, haystack)
middle_ix = haystack.length / 2

if haystack.empty?
false
elsif haystack[middle_ix] == needle
true
elsif haystack[middle_ix] < needle
bsearch(needle, haystack[0...middle_ix])
else
bsearch(needle, haystack[(middle_ix + 1)..-1]
end
end
```

Coded and pasted here with no testing.

Third branch of the if compares in the wrong direction, so if the target is in the first half of the array, it would narrow to the second half. Whoops.

I felt my heart sink when it threw an exception on first run, but it turned out the error was forgetting to sort the test arrays in the test code, so all was ok :)

```
def bsearch(haystack, needle):
if len(haystack) == 0:

mid = len(haystack) >> 1

if haystack[mid] == needle:
return mid
elif needle < haystack[mid]:
return bsearch(haystack[:mid], needle)
else:
return bsearch(haystack[mid+1:], needle) + mid + 1

def test():
import random

random.seed()

def create_test_data(length):
values = []
for i in range(length):
values.append(random.randint(1, 1 << 30))

return sorted(values)

passes = 0
fails = 0

for run in range(20):
length = random.randint(1,50)
sample = create_test_data(length)

for i, v in enumerate(sample[:]):
try:
except ValueError:
print "Ummm, couldn't find %i in %s" % (v, sample)
raise

print "Error. bsearch returned %i for %i in %s" % (answer, v, sample)
fails += 1
else:
passes += 1

# Test "not in array" case, including at least one test for a value too small and a value too big.
tests = set(create_test_data(random.randint(1, 100))) - set(sample)

for test in tests:
try:
except ValueError:
passes += 1
except:
print "Error: threw an unexpected exception when attempting to find %i in %s" % (too_large, sample)
fails += 1
else:
print "Error: found %i at position %i when it shouldn't have in %s" % (too_large, answer, sample)
fails += 1

print "Passed %i Failed %i" % (passes, fails)

```

After I wrote the code in an editor, I did do about 4 example runs-through (algorithm in my head; pen and paper for variable store) which was how i remembered to add 1 to mid for the slice and return in the RHS block.
I’m not sure if that counts as cheating, but I’m pretty sure it doesn’t.
10mins. and maybe 20-30 more for the test code.

491. yal

Failed. (Python)

Failed on boundary case! (Only gave myself 15 minutes, but still…)

```def bsearch (haystack, lower, upper, needle):
if upper == lower:
return -1;

key = (lower + upper) / 2
if haystack[key] == needle:
return key
elif needle < haystack[key]:
return bsearch(haystack, lower, key-1, needle)
elif haystack[key] < needle:
return bsearch(haystack, key+1, upper, needle)

def binarysearch(haystack, needle):
return bsearch(haystack, 0, len(haystack)-1, needle)

haystack = [10, 33, 45, 46, 54, 81, 93, 94, 100]
needle=10
binarysearch(haystack, needle)
# Gave -1...
```
493. Matt

Mine did not run the first time I ran it. Syntax error. Fixing the syntax error, I popped the stack.

Crap.

494. I’m way late to the game, but if you are indeed tallying the results, add me to the list. I assumed arguments would not be null. Up to you whether you consider that a bug or not for the purposes of this exercise.

Recursive solution written in C#, in about an hour:

```
/// <summary>
/// Finds the given element in the given array.
/// </summary>
/// <returns>True if the element exists in the array.</returns>
static bool IsFoundByBinarySearch(int[] arrayToSearch, int elementToFind)
{
if (arrayToSearch.Length <= 0)
{
return false;
}

if (arrayToSearch.Length == 1)
{
return (arrayToSearch[ 0 ] == elementToFind);
}

int[] splitArray = new int[ arrayToSearch.Length / 2 ];

if (arrayToSearch.Length % 2 == 0)
{
if (elementToFind.CompareTo(arrayToSearch[ arrayToSearch.Length / 2 - 1 ]) <= 0)
{
Array.Copy(arrayToSearch, 0, splitArray, 0, arrayToSearch.Length / 2);
return IsFoundByBinarySearch(splitArray, elementToFind);
}

Array.Copy(arrayToSearch, arrayToSearch.Length / 2, splitArray, 0, arrayToSearch.Length / 2);
return IsFoundByBinarySearch(splitArray, elementToFind);
}

if (elementToFind.CompareTo(arrayToSearch[ arrayToSearch.Length / 2]) == 0)
{
return true;
}

if (elementToFind.CompareTo(arrayToSearch[ arrayToSearch.Length / 2]) < 0)
{
Array.Copy(arrayToSearch, 0, splitArray, 0, arrayToSearch.Length / 2);
return IsFoundByBinarySearch(splitArray, elementToFind);
}

Array.Copy(arrayToSearch, arrayToSearch.Length / 2 + 1, splitArray, 0, arrayToSearch.Length / 2);
return IsFoundByBinarySearch(splitArray, elementToFind);
}
```
495. Ryan,

It is astounding, but yours is the 500th comment on this entry!

It seems obvious to me from the problem description that you can assume the array reference is not null (i.e. there is actually an array!) but that zero is a perfectly good number of items for that array to contain. So programs that fail when passed a null Array are fine; programs that go crazy when asked to search and empty array fail the test, and diminish, and go into the west.

496. Some of you guys can write such compact code!! I wrote mine before reading the ‘no testing’ rule so here goes:

```private void BinarySearch()
{
ulong[] numberList = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296,
433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976,
7778742049, 12586269025, 20365011074 };

ulong searchNum = 1346269;

bool numFound = FindNumber(numberList, searchNum, numberList.Length - 1, 0);
numFound = FindNumber(numberList, (ulong)47, 0, numberList.Length - 1);
searchNum = 20365011074;
numFound = FindNumber(numberList, searchNum, 0, numberList.Length - 1);

}

private bool FindNumber(ulong[] numberList, ulong searchNum, int listStart, int listEnd)
{
int midItem = listStart;

if (listStart > listEnd)
{
midItem = listEnd;
listEnd = listStart;
listStart = midItem;
}

int itemCount = (listEnd - listStart) + 1;

if (itemCount > numberList.Length)
{
midItem = listStart = 0;
listEnd = numberList.Length - 1;
itemCount = numberList.Length;
}

if (itemCount == 1)
{
if (numberList[midItem] == searchNum)
{
return true;
}
else
{
return false;
}
}

if ((itemCount % 2) == 0)
{
midItem = listStart + itemCount / 2 - 1;
}
else
{
midItem = listStart + itemCount / 2;
}

if (numberList[midItem] == searchNum)
{
return true;
}

if (numberList[midItem] > searchNum)
{
return FindNumber(numberList, searchNum, listStart, midItem);
}
else
{
return FindNumber(numberList, searchNum, midItem + 1, listEnd);
}
}
```
497. Mike,

Congrats on the new comment record :o)

You seem to have struck a nerve with a lot of people. I know for one that I’ve learned something from participating.

Thanks,
Ryan

498. I had an off-by-one error, a comparison flip, and I forgot to propagate the slice offset back up the call chain.

```function binary_search(array, value, offset) {
var pivot_index = Math.floor(array.length / 2);

var pivot = array[pivot_index];

if (pivot == value)
return pivot_index + offset;
else if (array.length > 1) {
if (value < pivot)
return binary_search(array.slice(0, pivot_index), value, pivot_index);
else
return binary_search(array.slice(pivot_index, array.length), value, pivot_index);
} else
return null;
}
```

The last argument need to be zero when called by a user.

499. One more fix: the offset needs to be added to the pivot index in the recursive call.

500. @Jeff: Handling a haystack of length 0 certainly IS within the scope of this problem. An array with no elements is sorted (see: vacuous truth), and so is valid input. Also, it doesn’t appear that your code handles arrays of length 1 either (because len(haystack)/2 == 0 in that case).

501. Mac

Did it in *looks guilty* LabVIEW. Worked on first run. Fun post, thanks for the distraction!

502. Avi

@David Mihola: Yes, it probably is too complicated. But since “For the purposes of this exercise, the possibility of numeric overflow in index calculations can be ignored”, I didn’t worry about cleaning it up too much – I just copied what I originally wrote.

503. patrick_h

my cheat: I did this last week to demonstrate the principle to a friend. No copy+paste, though. All from my head. This is probably not the fastest way to do it.

def bsrch( d, target ) :
if len(d) is 1 and d[0] != target:
return None
print(“Searching “, d, ” for “, target)
midpoint = len(d)/2
value = d[midpoint]
if target == value:
return midpoint
else:
if value > target:
rval = bsrch( d[:midpoint], target )
if rval != None:
return rval
else:
rval = bsrch( d[midpoint:], target )
if rval != None:
return rval + midpoint

504. Seamus

Untested and took about 15 minutes.

{source}public static int search(List sortedHaystack, String needle) {
int startRange = 0;
int endRange = sortedHaystack.size() – 1;

while (endRange – startRange >= 0) {
int midRange = startRange + ((endRange – startRange) / 2);
String value = sortedHaystack.get(midRange);
int comparison = value.compareTo(needle);
if (comparison == 0) {
return midRange;
} else if (comparison < 0) {
startRange = midRange + 1;
} else {
endRange = midRange – 1;
}
}

throw new IllegalStateException("Unable to find needle.");
}
{/source}

505. Tristan
```public class BinarySearch {

public static void main(String []args){

int[] foo = {1,2,3,4,5,6,7,8,9,10};
System.out.println("position:"+search(foo,0,foo.length,4) +" value:4");
System.out.println("position:"+search(foo,0,foo.length,6) +" value:6");
System.out.println("position:"+search(foo,0,foo.length,9) +" value:9");
System.out.println("position:"+search(foo,0,foo.length,12) +" value:12");
System.out.println("position:"+search(foo,0,foo.length,0) +" value:1");
}

public static int search(int[] range, int min, int max, int value){
int mid = ((max - min)/2) + (min);//half of range offset by min
if (min >= max)
else if(value == range[mid])
return mid;
else if (value < range[mid]){
max = mid - 1;
return search(range,min,max,value);
}
else{
min = mid + 1;
return search(range,min,max,value);
}
}
}

```
506. acastle

Maybe 8 mins in PHP and running it in my head. Not proud of it in parts, and still haven’t tested it. My ego is afraid to…

```function bsearch(\$haystack, \$needle, \$lower_bound = 0, \$upper_bound = -1) {
if (count(\$haystack) == 0) {
return -1;
}

if (\$upper_bound == -1) {
\$upper_bound = count(\$haystack) - 1;
}

\$mid = \$lower_bound + floor((\$upper_bound - \$lower_bound) / 2);

if (\$haystack[\$mid] == \$needle) {
return \$mid;
} else if (\$haystack[\$mid] < \$needle) {
\$upper_bound = \$mid - 1;
} else if (\$haystack[\$mid] > \$needle) {
\$lower_bound = \$mid + 1;
}

if (\$lower_bound <= \$upper_bound) {
bsearch(\$haystack, \$needle, \$lower_bound, \$upper_bound);
}

return -1;
}
```
507. but I should read the instructions, sorry for the html mess:

```	/**
* binary search algorithm
* @param array which must be strictly ascending and must not contain null values
* @param toSearch
* @return index of the searched object or -1 if it wasn't found
*/
public static <T extends Comparable<T>> int binarySearch(T[] array, T toSearch) {
if (toSearch==null) {
throw new NullPointerException("toSearch must not be null");
}
if (array==null || array.length==0) {
return -1;
}
return binarySearchIntern(array,toSearch,0,array.length-1);
}

private static <T extends Comparable<T>> int binarySearchIntern(T[] array, T toSearch, int l, int r) {
int m = (l+r)/2;
int compare = toSearch.compareTo(array[m]);
if (compare==0) {
return m;
}
if (l<r) {
if (compare<0) {
if (l<m) {
return binarySearchIntern(array, toSearch, l, m-1);
}
} else {
return binarySearchIntern(array, toSearch, m+1, r);
}
}
return -1;
}
```
508. acastle

argh, right after posting it, I can see I pasted the wrong one. Middle should be:

```	} else if (\$haystack[\$mid] > \$needle) {
\$upper_bound = \$mid - 1;
} else if (\$haystack[\$mid] < \$needle) {
\$lower_bound = \$mid + 1;
}
```
509. He, not even interested in trying – it’s a sheer bullshit metric. I doubt that my mechanic is in the 0.1% that can take my tires off without a wrench, either, just using his bare hands.

;)

510. Dru

Ok, well, I haven’t been able to actually test this and it’s been a while since I’ve written C but here we go:

http://pastebin.org/160265

So, that was done in Notepad++ and I’m yet to compile it. Fingers crossed :)

Now to look at some of the answers :)

Andrew

511. David Mihola

@Avi: I see. And just in case: I didn’t mean to sound offensive – my intention was more to check if I was right than to tell you that your solution could be better – at least yours was correct whereas mine wasn’t…

512. Sam

Here is my implementation in Perl. I tested it with a simple lexically-sorted array (‘a’..’z’) and it seems to work. It will probably fail horribly with numerically-sorted arrays.

```# returns index of first item found in array that matches term, or undef if not found
sub bsearch {
my(\$term, \$array, \$start, \$end) = @_;

my \$middle = int((\$start + \$end) / 2);

if ( (\$term lt \$array->[\$start]) or (\$term gt \$array->[\$end]) or (\$start > \$end) ) {
return undef;
}
elsif (\$term lt \$array->[\$middle]) {
\$end = \$middle - 1;
}
elsif (\$term gt \$array->[\$middle]) {
\$start = \$middle + 1;
}
elsif (\$term eq \$array->[\$middle]) {
return \$middle;
}
else {
die "ERROR: s = \$start, e = \$end, m = \$middle, t = \$term, item = " . \$array->[\$middle] ;
}

bsearch(\$term, \$array, \$start, \$end);

}
```

Here is an example of how to call it:

```# lexically-sorted array
my @array = ('a'..'z');

my \$term = \$ARGV[0] || 'e';

my \$r = bsearch(\$term, \@array, 0, \$#array);

if (defined \$r) {
print "Found: \$term = " . \$array[\$r] . "\n";
}
else {
}
```
513. ```def search(n,h):
return search2(n,h,0,len(h)-1)

def search2(n,h,low,high):
if low > high:
return None
l = high-low+1
p = l/2 + low
pe = h[p]
if pe == n:
return pe
elif pe < n:
return search2(n,h,p+1,high)
return search2(n,h,low,p-1)
```

Testing didn’t reveal any bugs, if anyone finds a bug I’d be most interested in hearing it…

514. Jason Spencer

Decided to have another look….FAIL. Mine dies if the search is larger than the largest item in the array.

We should go back to the essence of this blog post. I think Bentley’s point was that after explaining the algorithm in english it sounds easy to write. Easy enough that any real programmer could probably spit out a working implementation without actually trying it. His point is that this is deceptive; the code is trickier than the explanation.

Perhaps because we’re plugging other peoples’ libraries together so often, we’re used to black boxes. I think that’s why so many people are appalled by the idea of not testing. Testing is quicker and easier than reading the source of the libraries you’re using.

515. @acastle: In your recurse I think it should be RETURN bsearch(…, but other than that your corrected version looks ok.

516. @Tristain: You are using max to be exclusive, correct? Then in the recurse when value < range[mid], you should not use mid-1 as the new max or you skip the index before mid as well. E.g. try adding a test case to search for 5 in your array.

517. Guilherme Melo

Manually tested with a few values and lists.

```def binary_search(a_list, elem):
if not a_list:
return False
index = len(a_list)/2

ret = cmp(elem, a_list[index])

if ret < 0:
return binary_search(a_list[0:index], elem)
elif ret > 0:
return binary_search(a_list[index + 1:len(a_list)], elem)
else:
return True
```
518. Untested but it should work

```        public static int bsearch (int value, int[] data) {
if (data.Length == 0)
return -1;
return bsearch (value, data, 0, data.Length - 1);
}

static int bsearch (int value, int[] data, int lowerIndex, int upperIndex) {
if (data [lowerIndex] > value)
return -1;
if (data [upperIndex] < value)
return -1;
if (lowerIndex == upperIndex) {
if (data [lowerIndex] == value)
return lowerIndex;
else
return - 1;
}
int pivot = lowerIndex + (upperIndex - lowerIndex) / 2;
var result = bsearch (value, data, lowerIndex, pivot);
if (result != -1)
return result;
if (pivot == upperIndex)
return -1;
return bsearch (value, data, pivot + 1, upperIndex);
}
```
519. Joshua Cole

I actually ended up doing a little testing before I posted it. Only error I found was forgetting that python list slices are [s,e) and not [s,e].

>>> 2 // 4
0
>>> 5 // 2
2
>>> 2 // 2
1
>>> 4 // 2
2
>>> 3 // 2
1
>>> my_list = [i for i in range(100)]
>>>
>>> def find_index_of_i(my_list, i):
… s = 0
… e = len(my_list) – 1
… while True:
… if len(my_list[s:e]) <= 2:
… if my_list[s] == i: return s
… elif my_list[e] == i: return e
… else: return -1
… middle = s + (e – s) // 2
… if my_list[middle] == i: return middle
… elif my_list[middle] i: e = middle

>>> find_index_of_i(5)
Traceback (most recent call last):
File “”, line 1, in
TypeError: find_index_of_i() takes exactly 2 arguments (1 given)
>>> find_index_of_i(imy_list, 5)
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘imy_list’ is not defined
>>> find_index_of_i(my_list, 5)
-1
>>> 99 // 2
49
>>> 49 // 2
24
>>> 3 // 2
1
>>> my_list = [i for i in range(100)]
>>>
>>> def find_index_of_i(my_list, i):
… s = 0
… e = len(my_list) – 1
… while True:
… if len(my_list[s:e + 1]) <= 2:
… if my_list[s] == i: return s
… elif my_list[e] == i: return e
… else: return -1
… middle = s + (e – s) // 2
… if my_list[middle] == i: return middle
… elif my_list[middle]
i: e = middle

>>> find_index_of_i(my_list, 5)
5
>>> find_index_of_i(my_list, 10)
10
>>> find_index_of_i(my_list, 20)
20
>>> find_index_of_i(my_list, 21)
21
>>> [0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
>>> li = [0, 1, 2, 3, 4, 5]
>>> li[0]
0
>>> find_index_of_i(my_list, 0)
0
>>> find_index_of_i(my_list, -30)
-1

520. Viktor Skarlatov
```int find(int *arr, int beg, int end, int num)
{
int half = beg + (end - beg) / 2;
while(beg <= end)
{
if(arr[half] == num)
{
return half;
}

if(arr[half] > num)
{
end = half - 1;
}

if(arr[half] < num)
{
beg = half + 1;
}

half = beg + (end - beg) / 2;
}

return -1;
}
```
521. As I said, I’m confident that my solution works, i hope that I’m correct.

Still it’s fair to note that i almost forgot a couple of details, for example, i almost left line 18 as int pivot = (upperIndex – lowerIndex) / 2; forgetting to add up lowerIndex again to the pivot, and line 22 was a nearly miss to, i almost forgot to check for the pivot becoming greater than the upperIndex when i add 1 to it on line 24.

As they say, the devil is on the details :p

522. Michael H.

Wait, “NO TESTING until after you’ve decided your program is correct.” ?

I’m a Lisp programmer. There’s no such thing as “not testing”, since I test every little bit in the REPL as I go.

523. Here’s a test harness for a Javascript function following the same contract as mine (which passed):

```function testSearch(find) {
for (var length = 0; length < 10; ++length)
for (var times = 100; 0 < times; --times) {
var array = randomArray(length, length);
array.sort();
var key = randomInt(length+2) - 1;
var j = find(array.slice(0), key);
if (j === null)
assert(-1 === array.indexOf(key), "-1 === array.indexOf(key)");
else {
assert(0 <= j, "0 <= j");
assert(j < length, "j < array.length");
assert(key === array[j], "key === array[j]");
}
}
}

function randomArray(length, range) {
var array = [];
for (var i = 0; i < length; ++i)
array[i] = randomInt(range);
return array;
}

function randomInt(range) {
return Math.floor(range * Math.random());
}

function assert(ok, message) {
if (!ok)
throw new Error("Assertion failed: " + message);
}```
524. André Silva

So far, my implementation has passed all the tests (surprisingly!). I did this in about 8 minutes and to be honest I didn’t even consider some cases (e.g. empty arrays) but so far every test I did has passed. Also my implementation does not add +1 or -1 to the middle index, does anyone care to tell me if my implementation is “good”?

```
public class binarySearch {

public static int binary_search(int[] array, int element) {

return binary_search(0, array.length, array, element);
}

public static int binary_search(int lower_bound, int upper_bound, int[] array, int element) {

int middle = (upper_bound + lower_bound) / 2;

if(lower_bound == middle || upper_bound == middle)
return -1;

if(array[middle] < element)
return binary_search(middle, upper_bound, array, element);
else if(array[middle] > element)
return binary_search(lower_bound, middle, array, element);
else if(array[middle] == element)
return middle;

else return -1;
}

public static void main(String[] args) {

int array[] = {1,2,5,6,7,9,10,13,19,20,200};
int element = 200;

int position = binary_search(array, element);

System.out.println("Element " + element + " is at position " + position);
}
}
```
525. BTW it’s a bit boggling to see the solutions doing array slices. They’re O(n).

526. André: try binary_search({0}, 0).

527. Tristan

@Eric Good Call!

528. André Silva

Nice catch Darius. This test condition is wrong

```if(lower_bound == middle || upper_bound == middle)
return -1;
```
529. Wrote it in Java, recursively. And got the recursion wrong the first time – but that’s what unit tests are for :)

```    private int doBinSearch(final int[] data, final int lower, final int upper, final int search)
{
if (lower >= upper)
{
if (data[lower] == search)
{
return lower;
}
return -1;
}
int middle = lower + (upper - lower) / 2;
final int middleValue = data[middle];
if (search == middleValue)
{
return middle;
}
if (middleValue > search)
{
return (doBinSearch(data, lower, middle - 1, search));
}
else
{
return (doBinSearch(data, middle + 1, upper, search));
}
}

```
530. This is one of the reasons that I favour use of ready-made libraries: Trying to write an own sorting/searching/whatnot algorithm is a beginner’s error (in and by it self). There are well-tested and highly performant libraries for such basic functions available in any established high-level language—only rarely is the small gains possible by a custom made solution enough to justify writing an algorith from scratch.

Even if such justification can be found (possibly writing the first such library for a newer language) the correct way is obviously to grab a good book on the topic, pick a suitable implementation, and (if needed) translate/modify it.

More generally, in today’s software development, the main task at hand is limiting and controling complexity of various kinds. One way this is done is re-use: A less optimized solution with re-use is usually preferable to an optimized special-purpose solution. (Notwithstanding that some libraries and frameworks are too bloated to always be acceptable.) We can hope for the return of small Unix tools that each individually are of sufficiently low complexity that such measures are not needed; however, in reality, we are stuck with ever growing applications with ever increasing complexity—and, in today’s world, the good developer is not the one who understands complex code and algorithms, but the one who avoids or manages them. A sad, but near inevitable development.

(I realize that this was likely not the point you were making.)

531. Aww, what the heck …

```	;======================
; assume:
;    ecx = v
;    ebx = *p
;    edi = p.size
;    esi = 0
;---------------------------------------
_loop:
cmp    esi, edi
jz     _quit
;---------------------------------------
mov    edx, edi
sub    edx, esi
shr    edx, 1
;---------------------------------------
cmp    ecx, [ebx + edx * 4]
jle    @F
lea    esi, [edx + 1]
jmp    _loop
;---------------------------------------
@@:
mov    edi, edx
jmp    _loop
;---------------------------------------
_quit:
mov    eax, esi
cmp    ecx, [ebx + esi * 4]
jz     @F
mov    eax, -1
@@:
;======================
```
532. So are these the bugs?

A is empty.
Can’t find T in certain places or certain sizes of A (even? odd? powers of 2?)
Goes into an infinite loop sometimes. (How do you test for this?)
Becomes a linear search sometimes (Did you test for this?)
Tries to access off the end.
T is less than the first or greater than the last element.
Does (a+b)/2, which overflows with ints. (Did anyone here find this one by testing?)*

*The last is a problem if you have 2^31 one-byte elements to search (it could happen!). Or would be if you were searching a function or disk file rather than an array. Or if you used 32-bit ints (not size_t) to index arrays in a 64-bit computer, which I think would be the more basic problem. Or, if you’re in Python 2.x not 3.x, overflow bumps you into long ints, and then your function returns a long int which could have cascading inefficiency effects :-(

533. LOL @ Vince’s assembly version. Short, too!

But, come on people — does no-one write COBOL any more? Or APL? Or ETA?

534. Oops, forgot:
Has a problem with duplicate entries.

535. In Redcode :-)

```          nop    <bot,           >size
_bsnext   mov.b  size,           ptr
div    #2,             ptr
jmn    _bscont,        ptr

mov.b  bot,            ptr
jmp    notfound,       >ptr

slt    @ptr,           find

sub.b  ptr,            size
mov.b  ptr,            bot
jmp    _bsnext

jmp    found

div    #2,             size
jmp    _bsnext
```
536. @vince: It doesn’t look like you’re handling 0-length arrays correctly? That is, if ecx == [ebx] when edi==0, 0 will be returned instead of -1. Assuming [ebx] doesn’t cause an exception in that case, that is.

537. Now ETA would be fun. But Mike, the task is surely yours….

538. I wrote the code in eclipse because it was already opened.
I did not get it right in the first try, I executed the code once, found a bug, and fixed, so this is the second try and it works fine :D

```public class FinderTest {
static int[] origArr = {0, 3, 5, 7, 9, 11, 13, 14, 17, 24, 50, 57, 60, 90};

public static void main(String[] args) {
int vtf = Integer.valueOf(args[0]);
int pos = binarySearch(origArr, vtf, 0, origArr.length - 1);
System.out.println(pos);
}

private static int binarySearch(int[] arr, int vtf, int start, int end) {
int idx = start + ((end - start) / 2);
int cval = arr[idx];
if (cval == vtf)
return idx;
if (idx == start)
return -1;
if (cval > vtf)
return binarySearch(arr, vtf, start, idx - 1);
if (cval < vtf)
return binarySearch(arr, vtf, idx, end);
return -1;
}
}
```
539. Just found a bug in the code I posted, the code cannot find the last element of the array, to fix, just remove the “-1” from the main, and pass the array length there instead of the last position.

540. Kaveh Shahbazian

let rec binSearch target sortedArray =
match sortedArray with
| [||] -> None
| _ ->
let maidenIndex : int = sortedArray.Length / 2
if target sortedArray.[maidenIndex] then binSearch target sortedArray.[(maidenIndex + 1)..(sortedArray.Length – 1)]
else Some(sortedArray.[maidenIndex])

541. Jeremy Cromwell
```    static int find(int el, Integer list[])
{
int spos = 0;
int epos = list.length;
int cpos;
while (spos < epos)
{
cpos = spos + ((epos-spos)/2);
if (el == list[cpos]) return cpos;
if (el < list[cpos])
{
epos = cpos;
}
else
{
if (spos == cpos) return -1;
spos = cpos;
}
}
return -1;
}
```

Wrote it in about 20 minutes, then tested it and it works great even when the element isn’t in the list.

542. Jeff

Here’s my best shot in Python. I just wrote it by hand, so I might have messed up the syntax a bit (although it looks ok).

search(val, data):
L = len(data)
mid = L / 2
mid_val = data[mid]
if val == mid_val:
return mid
if L <= 1:
return None
if val mid_val:
search(val, data[mid + 1 : L])

543. @eric: You’re right of course. the code doesn’t check for zero length arrays. [ebx] itself can’t cause an exception because ebx is a valid address on the heap, but nonetheless a bug’s a bug, and so take my seat among the 90%…

544. Kaveh Shahbazian

Didn’t work! And I have remembered gist: http://gist.github.com/373070

545. Ah, I see. The WordPress bug. Sorry for being notorious. If now it won’t paste properly then I’m done!
{source}
import util.Random
val toFind = args(0).toInt
val r = new Random()
val a = (for (i<- 1 to 100) yield r.nextInt(100)).toList.sort(_<_).toArray
def binsearch(x:Int, a:Array[Int],first:Int, last:Int):Int = [
if (last-first=x) return binsearch(x, a, first, mid)
else return binsearch(x, a, mid, last)
]
]
for (el<-0 to 99) println(el+":"+a(el))
val res = binsearch(toFind, a, 0,99)
println ("res="+res)

{/source}

546. Kaveh Shahbazian

I meant posting some code here didn’t work! But my code worked! :-) So I’v decided to make a gist! (I was thinking along my previous entries! OOps!)

547. aliher1911
```public static int search(int[] data, int sample) {
return doSearch(data, sample, 0, data.length);
}

private static int doSearch(int[] data, int sample, int from, int to) {
if (from>=to) return -1;
int middle = (from+to)/2;
if (data[middle]==sample)
return middle;
if (data[middle]<sample)
return doSearch(data, sample, middle+1, to);
else
return doSearch(data, sample, from, middle);
}
```
548. Rodney

Let’s try once more. A post somewhere up above says to use {source}…{/source} but with square brackets. (Do you think he meant angle brackets?

```def binSearch( array, item ):
low = 0
high = len(array)
while (high>low):
mp = (high+low)/2
if (array[mp].key == item): break
if (array[mp].key < item):
low = mp+1
else:
high = mp
if (high>low):
return array[mp]
return None
```
549. Arghhh I surrender ! Is it because I use FireFox/Ubuntu? Anyway, in my blogspot blog it got pasted properly: http://anaivecoder.blogspot.com/2010/04/binary-search-script.html :)

550. Well, I thought I had it, I really did. It seemed right until I hit an edge case, an array of 2 items with the first of the 2 equal to the search value.

So I guess that puts me in the fail category as well. But here it is after I debugged (mentally walked through the code line by line to see where it was missing the value). Really, I should have thought of the edge case before I tested. :-/

```function bsearch(\$value, &\$array)
{
sort(\$array);
\$tmp = \$array;
\$len = count(\$array);
\$position = 0;
while (\$len > 1)
{
\$mid = floor(\$len/2);
if (\$tmp[\$mid] == \$value)
{
return \$position+\$mid;
}
else if (\$tmp[\$mid] > \$value)
{
\$tmp = (\$len > 2)?array_slice(\$tmp, 0, \$mid-1):array(\$tmp[0]); // initially did not check for 2 value array and would fail if \$tmp[0] == \$value
\$len = count(\$tmp);
//position does not change
}
else // \$array[\$mid] is < \$value
{
\$tmp = array_slice(\$tmp, \$mid+1);
\$len = count(\$tmp);
// position shifts right
\$position += \$mid+1;
}
}
if (\$tmp[0] == \$value) return \$position;
else return -1;
}
```
551. Here was my initial attempt in ruby:

def binary_search(to_find, sorted_array)
return false if sorted_array.empty?
middle_idx = sorted_array.size / 2
middle = sorted_array[middle_idx]
return middle if middle == to_find
return binary_search(to_find, sorted_array[0..middle_idx]) if to_find middle
end

For the keen eyed, this does contain a mistake that I discovered in my quick testing attempts.

My subsequent, corrected version is as follows:

def binary_search(to_find, sorted_array)
return false if sorted_array.empty?
middle_idx = sorted_array.size / 2
middle = sorted_array[middle_idx]
return middle if middle == to_find
return binary_search(to_find, sorted_array[0…middle_idx]) if to_find middle
end

Points for those who spot the differences ;) (There are two :) )

552. JEIhrig

Mike,

You wrote: “JEIhrig ,please check once more the instructions at the bottom of the post on how to post code in a WordPress comment. If you don’t do this, then . Repost your comment using the correct form, and I will delete the old broken version.”

I already read that but must have missed the instruction to replace the curly brackets with square ones. It wasn’t just the ‘greater than’ symbol that was missing but commented code somehow became uncommented, and another section was altogether missing, which lead me to believe it wasn’t mis-interpreted by wordpress but actually changed by someone. If it posts correctly this time, hopefully all my previous posts will be deleted.

```//I have not attempted to compile this
int search(int *list, int high, int low, int key)
{
int mid;
mid = (low + high) / 2;
if (high == low)
{
return key;
}
else if (key < list[mid])
{
return search(list, low, mid, key);
}
//The next line is commented like that intentionally. Please do not uncomment.
else //if (key > list[mid])
{
return search(list, mid + 1, high, key);
}
}
```

After re-pasting my code for the third time, (Still not compiling) I noticed a problem. It returns ‘key’ whether or not it’s in the list. So I changed that. (Does it still count if I made a modification after initial submission though I never compiled?)

```//I have not attempted to compile this
int search(int *list, int high, int low, int key)
{
int mid;
mid = (low + high) / 2;
if (high == low)
{
//Return true if it's in the list
return key == list[mid];
//Or this if you want the index
//return mid;
}
else if (key < list[mid])
{
return search(list, low, mid, key);
}
//The next line is commented like that intentionally. Please do not uncomment.
else //if (key > list[mid])
{
return search(list, mid + 1, high, key);
}
}
```
553. JEIhrig, I have deleted your previous posts now that this one is up, and properly formatted. Yes, I think it’s fine to change your submission so long as you make your change by inspection rather than only realising after tests have shown you the problem. Let us know how the tests go!

554. Pat

failed.

555. I tried it. But I couldn’t help testing — not confident enough in my code to do that! And sure enough I got it wrong. Several times. Having test cases help.

And, it’s one thing to have test cases. It’s another to have test cases that a) cover all cases, and b) are themselves correct!

Since I didn’t obey the rules, my submission doesn’t count… but posted anyways.

```let bsearch arr value =
let rec loop x y =
let range_length = y - x in
let midpoint = if range_length land 1 = 1
then range_length / 2 + 1 else range_length / 2
in
let mid = x + midpoint in
if range_length <= 0 then false
else if range_length = 1 then arr.(x) = value
else if arr.(mid) = value then true
else if arr.(mid) < value then
(* search right hand side *)
loop (mid+1) y
else
(* search left hand side *)
loop x mid
in loop 0 (Array.length arr)
```
556. D'Archangel

You know, not being allowed to test while writing code really screws with my TDD brain. Anyway, here’s a proposed solution. Yes, it’s iterative.

Note that this code is in fact also in the never-run class. It checks out as syntactically correct, but I am braced to be horribly embarrassed by what happens once I run it.

```#!/usr/bin/perl
use strict;
use warnings;

use POSIX qw(floor);

sub binsearch {
my (\$what, @ary) = @_;
# returns the index in sorted @ary that has \$what

my (\$start, \$end) = (0, \$#ary);
return unless defined \$end; # @ary is empty

while (\$start <= \$end) {
my \$middle = \$start + floor((\$end - \$start) / 2);
if (\$ary[\$middle] < \$what) {
\$start = \$middle + 1;
} elsif (\$ary[\$middle] > \$what) {
\$end = \$middle - 1;
} else {
return \$middle;
}
}

return;
}
```
557. D'Archangel

Huzzah. It passes the test suite. If there’s a bug, it’s subtle enough that I didn’t think to test for it.

D’A

558. Greg

Not tested, written in 10-15 mins :

(pseudo-code)

```
int bsearch(value, array) {

min = 0;
max = lenght(array) - 1;

while(max > min) {
int mid = min + max / 2;
if (value <= array(mid)) {
max = mid;
} else {
min = mid + 1;
}
}

//Now min = max
if (array[min] == value) {
return min;
} else {
return -1;
}

}
```

After reading what other did in the comments, I realized that I wrote :
int mid = min + max / 2;

int mid = min + (max-min) / 2;

So I guess I failed the test…

559. Luke Stebbing

Not tested:

```from __future__ import division

def bsearch(x, xs):
"""
Locate the index of a value in a sorted list.

Returns an index such that xs will still be sorted after calling xs.insert(index, x).

If xs is not sorted, the behavior is undefined.

"""
def recursive_bsearch(lower, upper):
"""Recursively search a closed-open range."""
middle = int((lower + upper) / 2)
# Don't evaluate xs[middle] if it falls outside the range.
if middle == upper or x == xs[middle]:
return middle
# Shrink the closed-open range, being sure to exclude middle.
if x < xs[middle]:
upper = middle
else:
lower = middle + 1
return recursive_bsearch(lower, upper)
return recursive_bsearch(0, len(xs))
```
560. Pingback: Top Posts — WordPress.com

561. acastle

Eric Burnett: “@acastle: In your recurse I think it should be RETURN bsearch(…, but other than that your corrected version looks ok.”

LOL, and that’s all it takes to fall into the 90%. One missed keyword and my function always returns -1, unless the item happens to be in the middle of the array on the initial call.

Funny how reading through it, my mind interprets that function call as implicitly returning.

562. Vitor

I went with a simple recursion in Java. I found some bumps along the road while testing, but haven’t found the need to alter the search at all after I finished and decided to start testing.

```public Integer bsearch(int[] array, int start, int finish, int target) {
if (start > finish) {
return null;
}

int middle = (start + finish)/2;

if (array[middle] == target) {
return middle;
} else if (array[middle] > target) {
return bsearch(array, start, middle-1, target);
} else {
return bsearch(array, middle+1, finish, target);
}
}
```

ps: actually, I made mistakes when testing, like forgeting I had a null return and printing out the array with the result as index, which obviously got a null pointer exception. Nothing on the bsearch itself, would like to see if I had any obvious mistake I still can’t see.

563. @JEIhrig: If key == list[mid], your code hits the else case and recurses with “return search(list, mid + 1, high, key);”, skipping that element and eventually returning false.

@Greg: Mike said to ignore integer overflow in this, so you don’t have to worry about that case. However, it doesn’t look like you handled the case of array being empty, however :(.

@Luke Stebbing: You do not handle the case where x is not in xs, nor when xs is empty. Essentially, there is no path for your code to return -1/False/None.

564. The second edition doesn’t change this passage.

seems to work, finds all the names in the list, and returns nil if the name wasn’t there

```def bsearch( list, item )
return bsearchrec( list, 0, list.size()-1, item)
end

def bsearchrec( list, first,last, item )
mid = (first+last)/2

if (list.at(mid) == item)
return item
elsif first == last
return nil
else
if( item < list.at(mid) )
return bsearchrec(list, first, mid-1, item)
else
return bsearchrec(list, mid+1, last, item)
end
end
end
```
566. YC

Seems like my last comment didn’t go through. Anyway I have to say this is a little hard to believe. Where do they find those 90% of “professional” programmers? BSearch is seriously not that difficult to write. Anyway here’s my untested version in python:

```# Returns the index of data in inArray, or -1 if none found
def BinarySearch(inArray, data):
start = 0
end = len(inArray) - 1
if end < start:
return -1
if data < inArray[0] or data > inArray[-1]:
return -1
while (True):
if (start == end):
if data == inArray[start]:
return start
else:
return -1
middle = start + ((end-start) / 2)
if (data == inArray[middle]):
return middle
elif (data < inArray[middle]):
end = middle
else:
start = middle + 1
```
567. YC

Here are my test code btw:

```def Test(inArray, data):
ret = BinarySearch(inArray, data)
print "BinarySearch(",
print inArray,
print ", ",
print data,
print ") = ",
print ret

print
Test([], 4)
print
Test([1], -1)
Test([1], 1)
Test([1], 2)
print
Test([1, 3, 5], 0)
Test([1, 3, 5], 1)
Test([1, 3, 5], 2)
Test([1, 3, 5], 3)
Test([1, 3, 5], 4)
Test([1, 3, 5], 5)
Test([1, 3, 5], 6)
```

```import Data.Array

mb :: Int -> Int -> Maybe (Int, Int)
mb n m | n <= m    = Just (n, m)
| otherwise = Nothing

chop :: (Int, Int) -> (Maybe (Int, Int), Int, Maybe (Int, Int))
chop (n, m) = (mb n (x-1), x, mb (x+1) m)
where
x = (m + n) `div` 2

search :: Ord a => Array Int a -> a -> Bool
search arr x = go (uncurry mb (bounds arr))
where
go Nothing   = False
go (Just ys) = case chop ys of
(l, i, r) -> case compare x (arr!i) of
LT -> go l
EQ -> True
GT -> go r
```
569. Ben Van Hof

This code passed all my tests the first time, so I’ll tentatively claim success. Though if I’m proven wrong, that’ll mean both my code AND my tests were crap…

```int binsearch(int *arr, int size, int target) {
int i, min = 0, max = size - 1;

while (min >= 0 && max < size && min <= max) {
i = ((max - min) / 2) + min;

if (arr[i] > target)
max = i  - 1;
else if (arr[i] < target)
min = i + 1;
else
return i;
}

return -1;
}
```
570. Stephen

Worked first time, took 7 minutes to code in Java including unit testing.

I would not expect any developer to create a correctly working implementation first time, as there are too many ways to make easy mistakes – however, I would expect a good developer to be able to write, test, and complete a solid implementation in less than 30 minutes.

571. Allen

I’m relatively new to programming and this was a fun challenge. Reading up it looks like my PHP solution is pretty close to Fred’s.

In retrospect the code feels a bit too easy to trip up though – reading the comments I can see there’s quite a few cases I didn’t account for.

```<?php
/*
Qualifictions
--Not accounting for possibility that needle isn't in haystack.
--No infinite loop protection if my code breaks.

Assumes an array is passed in indexed with numeric keys beginning with 0.

*/
function binary_search(\$haystack, \$needle)
{
\$lowLimit	= 0;
\$highLimit	= count(\$haystack) - 1;
\$found 		= false;

while (\$found == false)
{
\$range = \$highLimit - \$lowLimit;

if (\$range%2 != 0)
{
if (\$haystack[\$highLimit] == \$needle) {
\$found = \$highLimit;
}
\$highLimit--;
\$range--;
}

\$focus = (\$lowLimit + (\$range/2));

switch (\$haystack[\$focus])
{
case (\$haystack[\$focus] == \$needle):
\$found = \$focus;
break;
case (\$haystack[\$focus] > \$needle):
\$highLimit = \$focus - 1;
break;
case (\$haystack[\$focus] < \$needle):
\$lowLimit = \$focus + 1;
break;
}
}
return \$found;
}
```
572. Mark Ransom

In sporadic testing of my previous entry over the last 24 hours, I haven’t found a single case that fails, including the tests kindly provided by Steve Witham. While this isn’t completely conclusive, it’s a good sign that I’m in the 10%.

A few notes:

Writing the code took about 6 minutes. I spent another 5 scrutinizing the code to make sure I didn’t miss anything. I did try to import the code into the shell, which uncovered a syntax error that I fixed before my initial post (this was allowed by the rules).

My solution didn’t include the workaround for overflow problems, but I’m not sure Python is susceptible to that particular issue. I know I’ve used the workaround in previous incarnations in the distant past; I don’t think I’ve worried about it since 16-bit days. It’s quite unlikely that I’ll feed it an array of greater than 2^30 in size, and the rules explicitly state that overflow can be ignored.

I’m also quite surprised by the submissions that used slicing to divide the input array, because it defeats the whole purpose of a binary search. Binary search is supposed to be a O(log n) algorithm, but slicing is an O(n) operation.

573. Ian

I can’t believe how few posters did this in Perl. My first pass was recursive (and worked) but for kicks I converted it to iterative (and forgot to save the old version).

```sub bs {
\$needle = shift;
while (@_) {
my \$i = int(@_/2);
my \$cmp = \$needle <=> \$_[\$i];
if (\$cmp == 0) {
return 1;
} elsif (\$cmp == -1) {
splice(@_,\$i);
} elsif (\$cmp == 1) {
splice(@_,0,\$i+1);
}
}
return 0;
}
```
574. Luke Stebbing

@Eric Burnett: As I mention in bsearch()’s docstring, I’m interpreting the problem as “return the index where insertion preserves sorting”. IIRC, the original post didn’t state how edge cases should be reported, and I find that returning a valid index in all cases is much more useful than returning -1 or None. (I picked that up from the C++ STL convention of returning v.end() on a failure to match.)

Given an empty list, my code returns 0, indicating that [].insert(0, value) preserves sorting: [] is sorted, as is [value]. Given bsearch(3, [1, 2, 4]), by inspection I believe I properly return 2, which is the position where 3 should be inserted to maintain sorted order. (I don’t have a development environment set up on my iPad yet, so I can’t verify that. That’s also the reason I didn’t test my solution.)

575. Carl

After further analysis, I fail. Specifically, I will fail to find array(2) if array has size 6. Amusingly, I found the flaw by analyzing the code, and not by testing!

576. @Luke Stebbing: Hmm, fair point. I should have read your doc string more carefully – I retract my comments :).

577. Daniel

shit, didn’t read the quoting instructions fully:

```def bsr(target, list)
len = list.length
mid = len/2;

if(len == 0)
return false;
elsif(len == 1)
return list[0] == target;
elsif(target < list[mid])
return bsr(target, list[0,mid]);
else
return bsr(target, list[mid+1,len-1]);
end
end
```
578. Tomas Henriquez

def bs(array,findme):
if(array):
array = sorted(array)
len = array.__len__()

pos=len/2
mid=len/2+1

while(mid):
#trunk because its an integer
if mid%2 and mid != 1: mid=mid/2+1
else: mid=mid/2
if (findme == array[pos]):
return array[pos]
elif (findme > array[pos]):
pos+=mid
elif (findme len-1 or pos < 0): break

return "None"

a = [1,5,3,4,7,8,9]
print bs(a,9)
a = [1,5,4,3,9]
print bs(a,-12)
print bs(a,3)
a = [-19,-3,34,5,9,12]
print bs(a,-32)
print bs(a,34)
print bs(a,324)
a = [-21,-3,14,42,54,2,43,1,5,7,2,-14,423,-3]
print bs(a,-21)
print bs(a,423)
print bs(a,12424)
print bs(a,7)

579. Tomas Henriquez

oh fack… i hate wordpress, well deduce the tabs hehe

580. Success. Or, erm, at least it passes the tests I tried.

Code:

```        public static int BinarySearch<T>(T[] array, T item)
where T : IComparable<T>
{
if (array == null) throw new ArgumentNullException("array");
int startIndex = 0, endIndex = array.Length;
while (startIndex < endIndex)
{
int middleIndex = startIndex + (endIndex - startIndex) / 2;
T middleItem = array[middleIndex];
int comparison = item.CompareTo(middleItem);
if (comparison > 0)
startIndex = middleIndex + 1;
else if (comparison < 0)
endIndex = middleIndex;
else
return middleIndex;
}
return -1;
}```

Tests:

```        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void ArgumentNullException_Is_Thrown() { BinarySearch(null, 0); }
[TestMethod]
public void Odd_Number_Of_Items_Middle() { Assert.AreEqual(2, BinarySearch(new int[] { 1, 2, 3, 4, 5 }, 3)); }
[TestMethod]
public void Even_Number_Of_Items_Middle_Minus_One() { Assert.AreEqual(2, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 3)); }
[TestMethod]
public void Even_Number_Of_Items_Middle_Plus_One() { Assert.AreEqual(3, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 4)); }
[TestMethod]
public void Even_First_Item() { Assert.AreEqual(0, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 1)); }
[TestMethod]
public void Even_Last_Item() { Assert.AreEqual(5, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 6)); }
[TestMethod]
public void Odd_First_Item() { Assert.AreEqual(0, BinarySearch(new int[] { 1, 2, 3, 4, 5 }, 1)); }
[TestMethod]
public void Last_Item() { Assert.AreEqual(4, BinarySearch(new int[] { 1, 2, 3, 4, 5 }, 5)); }
[TestMethod]
public void Nonexistant_Item_In_Middle() { Assert.AreEqual(-1, BinarySearch(new int[] { 1, 2, 3, 5, 6 }, 4)); }
[TestMethod]
public void Nonexistant_Item_Past_End() { Assert.AreEqual(-1, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 7)); }
[TestMethod]
public void Nonexistant_Item_Before_Beginning() { Assert.AreEqual(-1, BinarySearch(new int[] { 1, 2, 3, 4, 5, 6 }, 0)); }
[TestMethod]
public void Empty_List() { Assert.AreEqual(-1, BinarySearch(new int[] { }, 7)); }```
581. Peter Toneby

My solution found the correct value as far as I could determine with my test cases, but only returned a boolean. When I switched to use Steve Whithams test cases they expected a return value of position and steps I failed on the position (after converting my code to return those, of course). Not sure if that should count as a fail or sucess. Thanks to Steve for the test cases.

Here is the current code:

```def binary_search(arr, value, index=0, nsteps=0):
"""\
Return i, nsteps.
i is any int such that A[i] == T, else i = None
nsteps is the number of steps it took.
"""
if arr == None or arr == []:
return None, nsteps
if len(arr) == 1:
if arr[0] == value:
return index, nsteps
return None, nsteps
split = len(arr)/2
if arr[split] == value:
return index+split, nsteps
elif arr[split] > value:
return binary_search(arr[:split], value, index, nsteps+1)
elif arr[split] < value:
index += split + 1
return binary_search(arr[split+1:], value, index, nsteps+1)
```
582. C, 15 minutes.

```/** begin points to the start of the array,
*   end is (begin+length). Returns a pointer
int* bs(int* begin, int* end, int needle)
{
while(begin < end)
{
int* pivot = begin + (end-begin)/2;

if(needle < *pivot)
end = pivot;
else if(*pivot < needle)
begin = pivot+1;
else
return pivot;
}
return NULL;
}
```
583. Luke Stebbing is right — I didn’t specify what the search should return when the element is not in the array. That was careless of me (although I suppose I could pass the buck to Jon Bentley :-)). Luke, I did mean for an out-of-band value such as -1 to be returned, as most (I think all) of the other solutions have done; but your approach is not prohibited by my statement of the problem, so you get a pass. (Provided there are no other bugs, of course!)

By the way, I love that Eric is continuing to fight the good fight. Keep up the destructive work!

584. Got it correct (I guess) after 10 iteration or so right here in Firebug.
{source}
function bs(arr, num) {
lower = 0;
upper = arr.length – 1;
while (upper != lower) {
mid = Math.floor((upper + lower)/2);
if (num == arr[mid]) return mid;
if (mid == lower) return num == arr[upper] ? upper : null;
if (num arr[mid]) lower = mid;
}
return null;
}
{/source}

585. Dave Cleal

{source}
private static int find(int t, int[] list) {
if (list.length == 0) {
return -1;
}
return find(t, list, 0, list.length-1);

}

private static int find(Integer t, int[] list, int lower, int upper) {
if (upper < lower) {
return -1;
}
int probe = (upper+lower)/2;
switch (t.compareTo(list[probe])) {
case 0:
return probe;
case -1:
return find(t, list, lower, probe-1);
case 1:
return find(t, list, probe+1, upper);
}
return -1;
}
{/source}

(Java) no idea if it works yet, I'm dimly aware that "upper+lower" might overflow for a truly gigantic array, but decided not to worry about that.

586. jasper

10 minutes, failed at testing for using

`<`

`<=`

:(

```def bsearch(li, val, lo=None, up=None):
if lo is None or up is None:
lo = 0
up = len(li)

# check that the value is inside the list
if val < li[lo]:
return None
if val > li[up - 1]:
return None
print li, val, lo, up

# the interval to check is [lo, up), check its size
if (up - lo) <= 1:
if li[lo] == val:
return lo
else:
return None

# slice and dice!
mid = (lo + up) / 2

if (li[mid] <= val):
return bsearch(li, val, mid, up)
else:
return bsearch(li, val, lo, mid)
```
587. ```
public static int binarySearch(int[] searchArray, int lowIndex, int highIndex, int searchKey) {
int index = -1;

if (lowIndex >= highIndex) {
index = -1;
} else {

int midIndex = (lowIndex + highIndex) / 2;
int midKey = searchArray[midIndex];

if (searchKey == midKey) {
index = midIndex;
} else if (searchKey < midKey) {
index = binarySearch(searchArray, lowIndex, (midIndex - 1), searchKey);
} else if (searchKey > midKey) {
index = binarySearch(searchArray, (midIndex + 1), highIndex, searchKey);
}
}

return index;
}

```
588. Groovy version:
``` def binarySearch(List tab, Number query){ if (tab.size() == 0) return null;```

``` ```

``` def s = 0, e = tab.size() -1 while (s<e){ int m = s+e/2 if (query <= tab[m]) e = m else s = m+1 } if (tab[s] != query) return null; return s; } ```

589. Luke Stebbing

@Mike Taylor: What I like about returning a valid index in all cases is it allows you to avoid a conditional expression when you don’t need one, i.e. if you’re using bsearch() to build a sorted list. The possibility of a wild and crazy index like -1 forces you to guard every single call in all situations.

I’ve firmly believed the “Make sure special cases are truly special” mantra ever since I encountered overly specific definitions in ninth-grade geometry, and I think I’m following that rule here by treating a failure to find the element normally.

Here’s an O(1) way to determine whether my bsearch() found the value. I really should’ve returned (index, found) in the first place, since that would’ve been a more useful signature. (I also should’ve used Python’s a // b shorthand instead of int(a / b), but I simply forgot.)

```index = bsearch(x, xs)
found = index != len(xs) and xs[index] == x
```
590. Ben Geore

Failed without testing……. yeah I forgot arrays dont always have to be an ‘even’ length ;). Once wrote a few tests, found ‘bug’ within minutes (seconds tbh).

591. Sorry, my first post seems to be screwed up. So I post again. I did not test the code before hand, and I did not follow the google blog link before writing this.

```int BinarySearch(vector<int> arr, int findThis)
{
if (arr.size() <= 0)
return -1;

int minIndex = 0;
int maxIndex = arr.size() - 1;

while (true)
{
int poolIndex = minIndex + ((maxIndex - minIndex) >> 1);

if ((minIndex >= arr.size() ||
maxIndex < 0 ||
maxIndex == minIndex) &&
arr[poolIndex] != findThis)
return -1;

if (arr[poolIndex] == findThis)
return poolIndex;
else if (arr[poolIndex] > findThis)
maxIndex = poolIndex - 1;
else if (arr[poolIndex] < findThis)
minIndex = poolIndex + 1;
}

return -1;
}
```
592. PHP, \$range is array, \$so is element to find

function binSearch(\$range, \$so) {
\$elems = count(\$range);
if (\$elems == 0) return false;
if (\$elems == 1) if (\$range[0] == \$so) return true; else return false;
\$middle = \$elems % 2 == 0 ? ((\$range[(\$elems/2)-1] + \$range[(\$elems/2)]) / 2) : \$range[floor(\$elems / 2)];
if (\$middle == \$so) return true;
\$range = (\$middle < \$so) ? array_slice(\$range, ceil(\$elems/2)) : array_slice(\$range, 0, floor(\$elems/2));
return binSearch(\$range, \$so);
}

593. — | maybe find a value a in a list of a. took about 20 minutes to be honest.
— admittedly i wrote it so it searched descending order lists 5,4,3,2,1 and realised
— this probably wasn’t desired, so changed “GT” to “LT”
find :: (Ord a) => a -> [a] -> Maybe a
find k [] = Nothing
find k xs = go (length xs) xs where
go len [x] | compare k x == EQ = Just x
| otherwise = Nothing
go len xs = go len’ xs’ where
xs’ = case last up `compare` k of
LT -> down
otherwise -> up
— i dunno if round 2.5 == 3
len’ | even len = len `div` 2
| otherwise = (len `div` 2) + 1
(up,down) = (take len’ xs,drop len’ xs)

seems to work alright

594. Jason B

def binary_search(a,s, l=0, u=nil)
u = a.length-1 if u==nil
x = l+(u-l)/2
return x if s==a[x]
return binary_search(a,s,l,x) if (s<a[x])
end

595. Kirill

Simple algorithm, takes an hour, but failed 3 stupid mistakes. Blame on me.

int bsearch1(int what, int elements, int* ar){
int max_el = elements – 1;
int min_el = 0;
//
for (;(min_el=0)&&(max_el<elements);){
int ix;
int delta;
//
if ( 0 != (max_el % 2)){
if (ar[max_el] == what)
return max_el;
— max_el;
};
if ( 0 != (min_el % 2)){
if (ar[min_el] == what)
return min_el;
++ min_el;
};
//
delta = (max_el – min_el)/ 2;
ix = min_el + delta;
//
if (ar[ix] what)
max_el = ix – 1;
else
return ix;
//
};
//
return -1;
};

596. Rodrigo B.

It took me like five minutes, no errors at the first try:

{source}
def bsearch(ary, val):
lo = 0
hi = len(ary)
oldm = -1
while True:
m = int((lo+hi)/2)
if oldm == m:
return -1
if val ary[m]:
oldm = m
lo = m
else:
return m
{/source}

My guess is that most programmers (even experienced ones) do not mentally check for the obvious edge cases while they’re coding.

597. This has passed all the tests I’ve thrown at it since writing it. (Python)

```def binary_search(array, value):
a = 0
b = len(array) - 1
while a <= b:
m = (b - a) / 2 + a
if array[m] == value:
return m
elif array[m] > value:
b = m - 1
else:
a = m + 1
return -1
```
598. Yay! I’m one of the best 10%! Below is my Java-source, I’ve made it generic instead of just ints.

```	/**
* Perform a binary search on a pre-sorted list.
*
* @param <T>					The type of the searchedValue, must implement {@link Comparable}
* @param listToBeSearchedIn	The list to search in
* @param searchedValue			The value to search
* @param start					The start index, inclusive
* @param end					The end index, exclusive
* @return						The index of searchedValue in listToBeSearchedIn, or -1 if not present
*/
public static <T extends Comparable<T>> int binarySearch(List<T> listToBeSearchedIn,
T searchedValue,
int start,
int end) {
int searchSize = end - start;
if(searchSize == 0) { //It is not in the list
return -1;
} else { //Split up the remaining search area and continue in one of the parts
int middle = start + (searchSize/2); //Division possibly truncated
int difference = searchedValue.compareTo(listToBeSearchedIn.get(middle));
if(difference == 0) { //We found it!
return middle;
} else if(difference < 0) { //Go left
return BinarySearch.binarySearch(listToBeSearchedIn, searchedValue, start, middle);
} else { //Go right
return BinarySearch.binarySearch(listToBeSearchedIn, searchedValue, middle+1, end);
}
}
}
```
599. Argh, layout is all fucked up. I guess I shouldn’t have used tabs… Anyway, clicking on ‘View Source’ helps a little…

600. @Mike: Thanks :). I should point out that I’m not checking 100% of them though… mis-formatted solutions I think code is missing from are skipped, as are languages I can’t wrap my head around yet (*cough* Haskell *cough*).

@Daniel: Just a nitpick – list[mid+1, len-1] is asking for len-1 elements starting at mid+1. Because there aren’t len-1 elements left you’ll get the ones to the end of the array (as desired), but it would be clearer to just say list[mid+1..len-1].

Also, as noted by other people, using array slices makes the algorithm O(n) rather than O(logn).

@Peter Toneby: What exactly you return is not specified, so not exactly matching someone else’s test cases is fine. I think if it passed in original form, that is enough. Your updated code looks good, although I will note that using array slices will make your search be O(n) not O(logn) as well.

@mondodello: It appears your code will mis-handle single element arrays (or ones that end up single element after recursion) since in that case, lowIndex == highIndex. If the first “if” is changed from greater-than-or-equal to just greater-than, I think your code would work.

@Piotr Gabryanczyk: “int m = s+e/2”: I think operator precedence will get you on this one.

601. failed to read instructions, tested before submitting, the only bug that uncovered was a ” which I’m sure I would have found by analysis.

{source}
int binarysearch(int *data, int sizeOfData, int lookFor)
{
int chopsize = sizeOfData / 2;
int index = chopsize;

// loop until the split size is 0 or value is found.
while( data[index] != lookFor && chopsize )
{
chopsize /= 2;

if (data[index] > lookFor)
index -= chopsize;
else
index += chopsize;
}

return (data[index]==lookFor)?index:-1;
}

{source}

602. Patrick
```int bsearch(int *L, int len, int T){
int i;
if len = 0
return -1;
i=len/2;
if L[i]=T
return i;
if L[i] < T
return bsearch(L+i+1, len-i-1, T);
if L[i] > T
return bsearch(L, i, T);
}
```

Failed miserably

603. Paul Annesley

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 #!/usr/bin/env ruby # # Are you one of the 10% of programmers who can write a binary search? def bin_search(search, subject) discarded_left = 0 while subject.any? mid = subject.length / 2 comparison = search <=> subject[mid] return comparison.zero? ? discarded_left : nil if subject.one? case comparison when –1 subject = subject[0…mid] when 1 subject = subject[mid…subject.length] discarded_left += mid else return discarded_left + mid end end end ### # Tests \$passes = 0 \$fails = 0 def assert_bin_search(expect, search, subject) found = bin_search(search, subject); pass = found === expect puts "FAIL: search:%d expect:%s got:%s in [%s]" % [search, expect.inspect, found.inspect, subject.join(',')] unless pass pass ? \$passes += 1 : \$fails += 1 end subject = [4, 5, 7, 11, 19, 29, 42, 69, 129, 182, 189, 190, 250] # test each value subject.each_with_index do |value, index| assert_bin_search(index, value, subject) end # test out-of-bounds and gaps ((0..500).to_a – subject).each do |value| assert_bin_search(nil, value, subject) end # test empty subject assert_bin_search(nil, 1, []) puts "Passes: #{\$passes} Fails: #{\$fails}"

view raw

binsearch.rb

hosted with ❤ by GitHub

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

 paulbookpro:binsearch paul\$ ./binsearch.rb Passes: 502 Fails: 0

view raw

output.txt

hosted with ❤ by GitHub

I broke rule #6; I guess test driven development has made me soft. My mind hasn’t been trained outside an iterative development model. And since we’ve evolved past punch-cards, I’m okay with that :)

604. Dmitry

I spent 17 minutes for thinking. After that I spent 21 minutes for writing test fixtures (that I will run only after all code finished).
After that I spent 9 minutes on binary search function.
At all it takes for me 47 minutes.
After that I run all tests and all works fine with first run!
After all I readed comments and links wih typical problems – all of them was solved by me during thinking.

there is my code:
http://pastie.org/928040

605. Dmitry, you should win some kind of prize: you belt-and-braces solution of both thinking and testing is clearly the way to go. I an encouraged that, after you’d invested the time into design, it worked first as intended the first time.

Now we wait for Eric to break it :-)

606. Ramesh
```#!/usr/bin/perl

sub bs {
my (\$pos, \$x, @ar) = @_;

if (\$#ar == 0) {
if (\$x == \$ar[0]) {
return \$pos;
} else {
}
}

if (\$x > \$ar[int(\$#ar/2)]) {
return bs(\$pos + int(\$#ar/2)+1, \$x, @ar[int(\$#ar/2)+1..\$#ar]);
} else {
return bs(\$pos, \$x, @ar[0 .. int(\$#ar/2)]);
}
}

my @test = (1,3,5,7,9,11,13,15,45,45,45,45,45,56,56,56,56,57);

print bs(0, 57, @test);
print "\n";
```

Seems to work.