summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorVarriount <Varriount@users.noreply.github.com>2014-03-27 15:08:19 -0400
committerVarriount <Varriount@users.noreply.github.com>2014-03-27 15:08:19 -0400
commitf40625f5c4634a426fa4e181abf54e0ffbe52d88 (patch)
tree7dafbaf23562b74203d439448a4ea133ad87e174
parent74af96dbf6b74627659f2f9a04152eaa10f7a17d (diff)
parent491291ae24fe5901f4be918cbce2d6c21a0ae0e9 (diff)
downloadNim-f40625f5c4634a426fa4e181abf54e0ffbe52d88.tar.gz
Merge pull request #1032 from barcharcraz/lowerBound
Added lowerBound function to the stdlib
-rw-r--r--lib/pure/algorithm.nim29
-rw-r--r--tests/stdlib/talgorithm.nim3
2 files changed, 32 insertions, 0 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 921c659de..49d1ac972 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -55,6 +55,35 @@ proc smartBinarySearch*[T](a: openArray[T], key: T): int =
 const
   onlySafeCode = true
 
+proc lowerBound*[T](a: openarray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
+  ## same as binarySearch except that if key is not in `a` then this 
+  ## returns the location where `key` would be if it were. In other
+  ## words if you have a sorted sequence and you call insert(thing, elm, lowerBound(thing, elm))
+  ## the sequence will still be sorted
+  ##
+  ## `cmp` is the comparator function to use, the expected return values are the same as
+  ## that of system.cmp
+  ## 
+  ## example:
+  ## `var arr = @[1,2,3,5,6,7,8,9]`
+  ## `arr.insert(4, arr.lowerBound(4))`
+  ## after running the above arr is `[1,2,3,4,5,6,7,8,9]`
+  result = a.low
+  var pos = result
+  var count, step: int
+  count = a.high - a.low + 1
+  while count != 0:
+    pos = result
+    step = count div 2
+    pos += step
+    if cmp(a[pos], key) < 0:
+      pos.inc
+      result = pos
+      count -= step + 1
+    else:
+      count = step
+
+proc lowerBound*[T](a: openarray[T], key: T): int = lowerBound(a, key, cmp[T])
 proc merge[T](a, b: var openArray[T], lo, m, hi: int, 
               cmp: proc (x, y: T): int {.closure.}, order: TSortOrder) =
   template `<-` (a, b: expr) = 
diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim
index 7ab652c82..3ca425fbc 100644
--- a/tests/stdlib/talgorithm.nim
+++ b/tests/stdlib/talgorithm.nim
@@ -6,3 +6,6 @@ doAssert product(@[@[1,2]]) == @[@[1,2]], "a simple case of one element"
 doAssert product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]], "two elements"
 doAssert product(@[@[1,2], @[3,4], @[5,6]]) == @[@[2,4,6],@[1,4,6],@[2,3,6],@[1,3,6], @[2,4,5],@[1,4,5],@[2,3,5],@[1,3,5]], "three elements"
 doAssert product(@[@[1,2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
+doAssert lowerBound([1,2,4], 3, system.cmp[int]) == 2
+doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
+doAssert lowerBound([1,2,3,10], 11) == 4
\ No newline at end of file