Add algorithm.upperBound (#7851)

* Add algorithm.upperBound
* Docs updated
This commit is contained in:
Dmitry Atamanov
2018-05-29 07:28:15 +03:00
committed by GitHub
parent 5866e64ebc
commit a075a912cf
2 changed files with 40 additions and 4 deletions

View File

@@ -57,6 +57,7 @@
- Added the proc ``times.convert`` for converting between different time units,
e.g days to seconds.
- Added the proc ``algorithm.binarySearch[T, K]`` with the ```cmp``` parameter.
- Added the proc ``algorithm.upperBound``.
### Library changes

View File

@@ -122,14 +122,14 @@ const
onlySafeCode = true
proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): 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
## Returns a position to the first element in the `a` that is greater than `key`, or last
## if no such element is found. 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 first version uses `cmp` to compare the elements. The expected return values are
## the same as that of system.cmp.
## The second version uses the default comparison function `cmp`.
##
## example::
##
@@ -150,6 +150,36 @@ proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.clo
proc lowerBound*[T](a: openArray[T], key: T): int = lowerBound(a, key, cmp[T])
proc upperBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
## Returns a position to the first element in the `a` that is not less
## (i.e. greater or equal to) than `key`, or last if no such element is found.
## In other words if you have a sorted sequence and you call
## insert(thing, elm, upperBound(thing, elm))
## the sequence will still be sorted.
##
## The first version uses `cmp` to compare the elements. The expected return values are
## the same as that of system.cmp.
## The second version uses the default comparison function `cmp`.
##
## example::
##
## var arr = @[1,2,3,4,6,7,8,9]
## arr.insert(5, arr.upperBound(4))
## # after running the above arr is `[1,2,3,4,5,6,7,8,9]`
result = a.low
var count = a.high - a.low + 1
var step, pos: int
while count != 0:
step = count shr 1
pos = result + step
if cmp(a[pos], key) <= 0:
result = pos + 1
count -= step + 1
else:
count = step
proc upperBound*[T](a: openArray[T], key: T): int = upperBound(a, key, cmp[T])
template `<-` (a, b) =
when false:
a = b
@@ -546,6 +576,11 @@ when isMainModule:
doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
doAssert lowerBound([1,2,3,10], 11) == 4
block upperBound:
doAssert upperBound([1,2,4], 3, system.cmp[int]) == 2
doAssert upperBound([1,2,2,3], 3, system.cmp[int]) == 4
doAssert upperBound([1,2,3,5], 3) == 3
block fillEmptySeq:
var s = newSeq[int]()
s.fill(0)