mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
add the std::sort::binarysearch module
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
committed by
Christoffer Lerno
parent
bbbcd9bf48
commit
55d17ec990
66
lib/std/sort/binarysearch.c3
Normal file
66
lib/std/sort/binarysearch.c3
Normal file
@@ -0,0 +1,66 @@
|
||||
module std::sort::binarysearch;
|
||||
|
||||
/*
|
||||
* Compare x and y and return one of the following values:
|
||||
* -1 if x < y
|
||||
* 0 if x == y
|
||||
* 1 if x > y
|
||||
*/
|
||||
def Comparer = fn int (void *x, void *y);
|
||||
|
||||
/**
|
||||
* Perform a binary search over the sorted array and return the smallest index
|
||||
* in [0, array.len) where cmp(i) is true and cmp(j) is true for j in [i, array.len).
|
||||
* @require is_array_or_subarray(array) "array must be an array or subarray"
|
||||
**/
|
||||
macro usz cmp_search(array, x, Comparer cmp)
|
||||
{
|
||||
usz i;
|
||||
for (usz j = array.len; i < j;)
|
||||
{
|
||||
usz half = (i + j) / 2;
|
||||
int res = cmp(&array[half], &x);
|
||||
switch {
|
||||
case res > 0: j = half;
|
||||
case res < 0: i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a binary search over the sorted array and return the index
|
||||
* in [0, array.len) where x would be inserted.
|
||||
* @require is_array_or_subarray(array) "array must be an array or subarray"
|
||||
**/
|
||||
macro usz search(array, x)
|
||||
{
|
||||
usz i;
|
||||
for (usz j = array.len; i < j;)
|
||||
{
|
||||
usz half = (i + j) / 2;
|
||||
switch {
|
||||
case greater(array[half], x): j = half;
|
||||
case less(array[half], x): i = half + 1;
|
||||
default: return half;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
macro bool is_array_or_subarray(slice) @private
|
||||
{
|
||||
$switch ($typeof(slice).kindof)
|
||||
$case POINTER:
|
||||
var $Inner = $typefrom($typeof(bytes).inner);
|
||||
$if $Inner.kindof == ARRAY:
|
||||
return true;
|
||||
$endif
|
||||
$case ARRAY:
|
||||
$case SUBARRAY:
|
||||
return true;
|
||||
$default:
|
||||
return false;
|
||||
$endswitch
|
||||
}
|
||||
37
test/unit/stdlib/sort/binarysearch.c3
Normal file
37
test/unit/stdlib/sort/binarysearch.c3
Normal file
@@ -0,0 +1,37 @@
|
||||
module binarysearch_test @test;
|
||||
import std::sort::binarysearch;
|
||||
|
||||
struct SearchTest
|
||||
{
|
||||
int[] data;
|
||||
int x;
|
||||
int index;
|
||||
}
|
||||
|
||||
fn void search()
|
||||
{
|
||||
SearchTest[] tcases = {
|
||||
{ {}, 0, 0 },
|
||||
{ {1, 2, 3}, 1, 0 },
|
||||
{ {1, 2, 3}, 2, 1 },
|
||||
{ {1, 2, 3}, 3, 2 },
|
||||
{ {1, 2, 3}, 4, 3 },
|
||||
{ {10, 20, 30}, 14, 1 },
|
||||
{ {10, 20, 30}, 26, 2 },
|
||||
};
|
||||
|
||||
foreach (tc : tcases)
|
||||
{
|
||||
usz idx = binarysearch::search(tc.data, tc.x);
|
||||
assert(idx == tc.index, "%s: got %d; want %d", tc.data, idx, tc.index);
|
||||
|
||||
usz cmp_idx = binarysearch::cmp_search(tc.data, tc.x, &cmp_int);
|
||||
assert(cmp_idx == tc.index, "%s: got %d; want %d", tc.data, cmp_idx, tc.index);
|
||||
}
|
||||
}
|
||||
|
||||
module binarysearch_test;
|
||||
|
||||
fn int cmp_int(void* x, void* y) {
|
||||
return *(int*)x - *(int*)y;
|
||||
}
|
||||
Reference in New Issue
Block a user