bsearch(x) (binary search): builtin.c (tested), with documentation and test case. Always yields an integer (even if input is unsorted); returns (-1 - ix) if x is not in input array.

This commit is contained in:
pkoppstein authored and Nicolas Williams committed 2014-12-27 18:44:20 -06:00
1 parent 56344670f4
commit 00f018a054
3 files changed
+58

No files matched your search

+31
View File
@@ -1161,6 +1161,37 @@ static const char* const jq_builtins[] = {
// # like ruby's upcase - only characters a to z are affected
"def ascii_upcase:"
" explode | map( if 97 <= . and . <= 122 then . - 32 else . end) | implode;",
// # Assuming the input array is sorted, bsearch/1 returns
// # the index of the target if the target is in the input array; and otherwise
// # (-1 - ix), where ix is the insertion point that would leave the array sorted.
// # If the input is not sorted, bsearch will terminate but with irrelevant results.
"def bsearch(target):"
" if length == 0 then -1"
" elif length == 1 then"
" if target == .[0] then 0 elif target < .[0] then -1 else -2 end"
" else . as $in"
"" // # state variable: [start, end, answer]
"" // # where start and end are the upper and lower offsets to use.
" | last( [0, length-1, null]"
" | while( .[0] <= .[1] ;"
" (if .[2] != null then (.[1] = -1)" // # i.e. break
" else"
" ( ( (.[1] + .[0]) / 2 ) | floor ) as $mid"
" | $in[$mid] as $monkey"
" | if $monkey == target then (.[2] = $mid)" // # success
" elif .[0] == .[1] then (.[1] = -1)" // # failure
" elif $monkey < target then (.[0] = ($mid + 1))"
" else (.[1] = ($mid - 1))"
" end"
" end )))"
" | if .[2] == null then" // # compute the insertion point
" if $in[ .[0] ] < target then (-2 -.[0])"
" else (-1 -.[0])"
" end"
" else .[2]"
" end"
" end;",
};
#undef LIBM_DD