Cashew updated, Sep 2007

Bill Baxter dnewsgroup at billbaxter.com
Tue Sep 4 19:45:01 PDT 2007


Chris Nicholson-Sauls wrote:
> Yet some more updates to Cashew.  Woooo.

> cashew.utils.Array : 0.12.0
>  -- Added .collect() pseudo-member
>  -- Changed pseudo-members returning 'void' to return 'T[]' instead, for 
> chaining.
>     This means you can do silly things like this:
>         array.unique.remove(foo).rotl(4);
>     :)

I sent you some binary search routines for array a while back.  Since 
you didn't put 'em in  I'll just post 'em here for anyone who needs to 
do binary searching:


/** Check that the array A is sorted in non-decreasing order */
bool is_sorted(T)(T[] A)
{
     size_t N = A.length;
     for(size_t i=1; i<N; i++) {
         if (A[i]<A[i-1]) return false;
     }
     return true;
}
unittest{
     int[] foo = [1,2,3,5,6];
     assert(foo.is_sorted());
     foo = [1,2,4,3,6];
     assert(!foo.is_sorted());
     foo = [];
     assert(foo.is_sorted());
     foo = [42];
     assert(foo.is_sorted());
}

/** Use binary search to look for x in A, which must be sorted.
     If there are multiple values that match, returns the value with
     the lowest index.  This method uses bisect_left() for the dirty work.

     Optional args lo (default 0) and hi (default A.length) bound the
     slice of A to be searched.
*/
size_t bsearch(T)(T[] A, T x, size_t lo=0, size_t hi=size_t.max)
in { assert(is_sorted(A)); }
body
{
     size_t ret = A.bisect_left(x,lo,hi);
     if (ret<hi && ret<A.length && A[ret]==x) {
         return ret;
     }
     return NOT_FOUND;
}
unittest{
     int[] foo = [1,3,4,6,8];
     assert(foo.bsearch(0) == NOT_FOUND);
     assert(foo.bsearch(1) == 0);
     assert(foo.bsearch(2) == NOT_FOUND);
     assert(foo.bsearch(3) == 1);
     assert(foo.bsearch(4) == 2);
     assert(foo.bsearch(5) == NOT_FOUND);
     assert(foo.bsearch(6) == 3);
     assert(foo.bsearch(7) == NOT_FOUND);
     assert(foo.bsearch(8) == 4);
     assert(foo.bsearch(9) == NOT_FOUND);
     int[] bar = [1,1,3,3,3,8,8];
     assert(bar.bsearch(0) == NOT_FOUND);
     assert(bar.bsearch(1) == 0);
     assert(bar.bsearch(2) == NOT_FOUND);
     assert(bar.bsearch(3) == 2);
     assert(bar.bsearch(4) == NOT_FOUND);
     assert(bar.bsearch(8) == 5);
     assert(bar.bsearch(9) == NOT_FOUND);
}


/** Use binary search to look for x in A, which must be sorted.
     If there are multiple values that match, returns the value with
     the highest index.

     Optional args lo (default 0) and hi (default A.length) bound the
     slice of A to be searched.
*/
size_t bsearch_right(T)(T[] A, T x, size_t lo=0, size_t hi=size_t.max)
in { assert(is_sorted(A)); }
body
{
     size_t ret = A.bisect(x,lo,hi);
     if (ret>lo) ret--;
     if (A[ret]==x) {
         return ret;
     }
     return NOT_FOUND;
}
unittest{
     int[] foo = [1,3,4,6,8];
     assert(foo.bsearch_right(0) == NOT_FOUND);
     assert(foo.bsearch_right(1) == 0);
     assert(foo.bsearch_right(2) == NOT_FOUND);
     assert(foo.bsearch_right(3) == 1);
     assert(foo.bsearch_right(4) == 2);
     assert(foo.bsearch_right(5) == NOT_FOUND);
     assert(foo.bsearch_right(6) == 3);
     assert(foo.bsearch_right(7) == NOT_FOUND);
     assert(foo.bsearch_right(8) == 4);
     assert(foo.bsearch_right(9) == NOT_FOUND);
     int[] bar = [1,1,3,3,3,8,8];
     assert(bar.bsearch_right(0) == NOT_FOUND);
     assert(bar.bsearch_right(1) == 1);
     assert(bar.bsearch_right(2) == NOT_FOUND);
     assert(bar.bsearch_right(3) == 4);
     assert(bar.bsearch_right(4) == NOT_FOUND);
     assert(bar.bsearch_right(8) == 6);
     assert(bar.bsearch_right(9) == NOT_FOUND);
}

/** Return the index where to insert item x in list A, assuming A sorted.

     The return value i is such that all e in A[0..i] have e <= x, and all
     e in A[i..$] have e > x.  So if x already appears in the list, i
     points just beyond the rightmost x already there

     Optional args lo (default 0) and hi (default A.length) bound the
     slice of A to be searched.
*/
size_t bisect(T)(T[] A, T x, size_t lo=0, size_t hi=size_t.max)
in { assert(is_sorted(A)); }
body
{
     if (hi == size_t.max) hi = A.length;
     size_t mid;
     while (lo < hi)
     {
         mid = (lo+hi)/2;
         if (x < A[mid]) { hi = mid; }
         else { lo = mid+1; }
     }
     return lo;
}
unittest{
     int[] foo = [1,3,4,6,8];
     assert(foo.bisect(0) == 0);
     assert(foo.bisect(1) == 1);
     assert(foo.bisect(2) == 1);
     assert(foo.bisect(3) == 2);
     assert(foo.bisect(4) == 3);
     assert(foo.bisect(5) == 3);
     assert(foo.bisect(10) == 5);
     int[] bar = [1,1,3,4,4,6,8,8];
     assert(bar.bisect(0) == 0);
     assert(bar.bisect(1) == 2);
     assert(bar.bisect(2) == 2);
     assert(bar.bisect(3) == 3);
     assert(bar.bisect(4) == 5);
     assert(bar.bisect(5) == 5);
     assert(bar.bisect(6) == 6);
     assert(bar.bisect(7) == 6);
     assert(bar.bisect(8) == 8);
     assert(bar.bisect(9) == 8);
}

/** Return the index where to insert item x in list A, assuming A sorted.

     The return value i is such that all e in A[0..i] have e < x, and
     all e in A[i..$] have e >= x.  So if x already appears in the
     list, i points at the leftmost x already there.

     Optional args lo (default 0) and hi (default len(a)) bound the
     slice of a to be searched.
*/
size_t bisect_left(T)(T[] A, T x, size_t lo=0, size_t hi=size_t.max)
in { assert(is_sorted(A)); }
body
{
     if (hi==size_t.max) hi = A.length;
     size_t mid;
     while (lo < hi)
     {
         mid = (lo+hi)/2;
         if (A[mid] < x) { lo = mid+1; }
         else { hi = mid; }
     }
     return lo;
}
unittest{
     int[] foo = [1,3,4,6,8];
     assert(foo.bisect_left(0) == 0);
     assert(foo.bisect_left(1) == 0);
     assert(foo.bisect_left(2) == 1);
     assert(foo.bisect_left(3) == 1);
     assert(foo.bisect_left(4) == 2);
     assert(foo.bisect_left(5) == 3);
     assert(foo.bisect_left(10) == 5);
     int[] bar = [1,1,3,4,4,6,8,8];
     assert(bar.bisect_left(0) == 0);
     assert(bar.bisect_left(1) == 0);
     assert(bar.bisect_left(2) == 2);
     assert(bar.bisect_left(3) == 2);
     assert(bar.bisect_left(4) == 3);
     assert(bar.bisect_left(5) == 5);
     assert(bar.bisect_left(6) == 5);
     assert(bar.bisect_left(7) == 6);
     assert(bar.bisect_left(8) == 6);
     assert(bar.bisect_left(9) == 8);
}




More information about the Digitalmars-d-announce mailing list