Add algorithm.upperBound (#7851)
* Add algorithm.upperBound * Docs updated
This commit is contained in:
parent
5866e64ebc
commit
a075a912cf
2 changed files with 40 additions and 4 deletions
|
|
@ -57,6 +57,7 @@
|
||||||
- Added the proc ``times.convert`` for converting between different time units,
|
- Added the proc ``times.convert`` for converting between different time units,
|
||||||
e.g days to seconds.
|
e.g days to seconds.
|
||||||
- Added the proc ``algorithm.binarySearch[T, K]`` with the ```cmp``` parameter.
|
- Added the proc ``algorithm.binarySearch[T, K]`` with the ```cmp``` parameter.
|
||||||
|
- Added the proc ``algorithm.upperBound``.
|
||||||
|
|
||||||
### Library changes
|
### Library changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,14 +122,14 @@ const
|
||||||
onlySafeCode = true
|
onlySafeCode = true
|
||||||
|
|
||||||
proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
|
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 a position to the first element in the `a` that is greater than `key`, or last
|
||||||
## returns the location where `key` would be if it were. In other
|
## if no such element is found. In other words if you have a sorted sequence and you call
|
||||||
## words if you have a sorted sequence and you call
|
|
||||||
## insert(thing, elm, lowerBound(thing, elm))
|
## insert(thing, elm, lowerBound(thing, elm))
|
||||||
## the sequence will still be sorted.
|
## 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 same as that of system.cmp.
|
||||||
|
## The second version uses the default comparison function `cmp`.
|
||||||
##
|
##
|
||||||
## example::
|
## 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 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) =
|
template `<-` (a, b) =
|
||||||
when false:
|
when false:
|
||||||
a = b
|
a = b
|
||||||
|
|
@ -546,6 +576,11 @@ when isMainModule:
|
||||||
doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
|
doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
|
||||||
doAssert lowerBound([1,2,3,10], 11) == 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:
|
block fillEmptySeq:
|
||||||
var s = newSeq[int]()
|
var s = newSeq[int]()
|
||||||
s.fill(0)
|
s.fill(0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue