# colomon/List-Utils

Added binary search algorithms previously found in LastOfTheCarelessM…

`…en's Vector repo, updating their tests to current Rakudo.`
1 parent 4878de0 commit babe643bd37fe191959da4c044fe065037114fed committed Sep 14, 2010
Showing with 70 additions and 0 deletions.
1. +1 −0 CREDITS
2. +40 −0 lib/List/Utils.pm
3. +29 −0 t/05-search.t
1 CREDITS
 @@ -1,3 +1,4 @@ Solomon Foster (colomon) Nuno Carvalho (smashz/smash) Moritz Lenz +SF (LastOfTheCarelessMen @ github)
40 lib/List/Utils.pm
 @@ -62,3 +62,43 @@ sub transpose(@list is copy) is export(:DEFAULT) { } } +sub lower-bound(@x, \$key) is export(:DEFAULT) { + my \$first = 0; + my \$len = @x.elems; + my \$half; + while (\$len > 0 && \$first < @x.elems) + { + \$half = \$len div 2; + if (@x[\$first + \$half] < \$key) + { + \$first += \$half + 1; + \$len -= \$half + 1; + } + else + { + \$len = \$half; + } + } + return \$first; +} + +sub upper-bound(@x, \$key) is export(:DEFAULT) { + my \$first = 0; + my \$len = @x.elems; + my \$half; + while (\$len > 0 && \$first < @x.elems) + { + \$half = \$len div 2; + if (@x[\$first + \$half] <= \$key) + { + \$first += \$half + 1; + \$len -= \$half + 1; + } + else + { + \$len = \$half; + } + } + return \$first; +} +
29 t/05-search.t
 @@ -0,0 +1,29 @@ +use v6; +use Test; +use List::Utils; + +plan *; + +my @array = (1, 2, 2, 3, 4, 5, 5, 5, 5, 6, 7, 8); + +ok(([<=] @array), "array is sorted properly"); + +for (1.5, 2, 2.5, 3, 3.5, 4, 5.5, 6, 8) -> \$x +{ + my \$i = lower-bound(@array, \$x); + ok(@array[\$i - 1] < \$x <= @array[\$i], "lower bound - 1 < \$x <= lower bound"); +} + +is(lower-bound(@array, 8.5), @array.elems, "Off the big end returns max_index + 1"); +is(upper-bound(@array, 0.5), 0, "Off the little end returns 0"); + +for (1.5, 2, 2.5, 3, 3.5, 4, 5.5, 6) -> \$x +{ + my \$i = upper-bound(@array, \$x); + ok(@array[\$i - 1] <= \$x < @array[\$i], "upper bound - 1 <= \$x < upper bound"); +} + +is(lower-bound(@array, 8), @array.elems - 1, "Equal to the big end returns max_index"); +is(lower-bound(@array, 8.5), @array.elems, "Off the big end returns max_index + 1"); + +done_testing;