diff options
author | Dmitry Atamanov <data-man@users.noreply.github.com> | 2018-05-29 07:28:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-29 07:28:15 +0300 |
commit | a075a912cfaba685ad1ba9e41d046265fdf104b8 (patch) | |
tree | 21843fae9e0b2dafc96c5333aa5b90f27f0fe27c | |
parent | 5866e64ebcc4d6a80fb3403b6a38317fe5a52e74 (diff) | |
download | Nim-a075a912cfaba685ad1ba9e41d046265fdf104b8.tar.gz |
Add algorithm.upperBound (#7851)
* Add algorithm.upperBound * Docs updated
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | lib/pure/algorithm.nim | 43 |
2 files changed, 40 insertions, 4 deletions
diff --git a/changelog.md b/changelog.md index 3482c9eba..27090a1df 100644 --- a/changelog.md +++ b/changelog.md @@ -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 diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 98330b680..81badfae6 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -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) |