Last active
February 1, 2017 14:38
-
-
Save binki/fdaa9d928143a1d68cb7ab2f94af9acd to your computer and use it in GitHub Desktop.
Binary search attempt
This file contains hidden or 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.
Learn more about bidirectional Unicode characters
class BinkiBinarySearch { | |
/** | |
Input: `arr` is a sorted array, `sought` is a sought value, | |
`cmp` a comparer which when called like `cmp(a, b)` returns -1 | |
if `a` comes before `b`, 0 if `a` and `b` are of the same | |
order, and 1 if `a` comes after `b`. | |
Returns: -1 if something equivalent to `sought` is not found, | |
index of any element matching `sought` otherwise. | |
**/ | |
static function bsearch<T>(arr:Array<T>, sought:T, cmp:T->T->Int) { | |
var min = 0; | |
var max = arr.length - 1; | |
while (min <= max) { | |
var i = min + Std.int((max - min)/2); | |
var val = arr[i]; | |
var cmpResult = cmp(sought, val); | |
if (cmpResult < 0) { | |
max = i - 1; | |
} else if (cmpResult > 0) { | |
// Ensure to avoid getting stuck where min=0, max=1, | |
// and min+(max-min)/2=0. | |
min = i + 1; | |
} else { | |
return i; | |
} | |
} | |
return -1; | |
} | |
static function main() { | |
// For validating syntax. | |
// Tests for my cmp function xD. I wrote cmp() wrong the first | |
// time according to the API of my bsearch(), I was able to | |
// get stuff working by fixing cmp() (I only added trace() | |
// debugging to bsearch() and then noticed that cmp() was | |
// behaving wrong then added these test cases). | |
expectCmp(0, 0, 0); | |
expectCmp(0, 1, -1); | |
expectCmp(1, 0, 1); | |
// Tests written after I decided to consider the interface | |
// frozen. | |
expect([], 2, -1); | |
expect([0,1,2], 2, 2); | |
expect([0,1,3], 2, -1); | |
expect([4,5,6], 2, -1); | |
expect([-1,0,1], 2, -1); | |
expect([0], 2, -1); | |
expect([3], 2, -1); | |
expect([2], 2, 0); | |
expect([0,1], 2, -1); | |
expect([1,2], 2, 1); | |
expect([1,3], 2, -1); | |
expect([4,5], 2, -1); | |
expect([2,3,4,5,6,7,8,9,10,11], 2, 0); | |
expect([1,2,3,4,5,6,7,8,9,10], 2, 1); | |
expect([0,1,2,3,4,5,6,7,8,9], 2, 2); | |
expect([-1,0,1,2,3,4,5,6,7,8], 2, 3); | |
expect([-2,-1,0,1,2,3,4,5,6,7], 2, 4); | |
expect([-3,-2,-1,0,1,2,3,4,5,6], 2, 5); | |
expect([-4,-3,-2,-1,0,1,2,3,4,5], 2, 6); | |
expect([-5,-4,-3,-2,-1,0,1,2,3,4], 2, 7); | |
expect([-6,-5,-4,-3,-2,-1,0,1,2,3], 2, 8); | |
expect([-7,-6,-5,-4,-3,-2,-1,0,1,2], 2, 9); | |
expect([0,1,3,4,5,6,7,8,9,10], 2, -1); | |
expect([-1,0,1,2,3,4,5,6,7,8], 2, 3); | |
} | |
static function cmp(a, b) return a - b; | |
static function expectCmp(a, b, expectedResult) { | |
var result = cmp(a, b); | |
if (result != expectedResult) { | |
throw 'Expected ${expectedResult} but got ${result}'; | |
} | |
} | |
static function expect(arr, sought, expectedIndex) { | |
var result = bsearch(arr, sought, cmp); | |
if (result != expectedIndex) { | |
throw 'Expected ${expectedIndex} but got ${result}'; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on the comment about using half-open ranges, I probably am not splitting down the middle quite and will tend to go slightly to the left because my ranges are not open?