From baa304f37013b6be642aa6c9ae20990b6c489573 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Sun, 23 Mar 2014 18:28:05 -0400 Subject: [PATCH 1/4] added lowerBound function to algorithm library --- lib/pure/algorithm.nim | 24 ++++++++++++++++++++++++ tests/stdlib/talgorithm.nim | 3 +++ 2 files changed, 27 insertions(+) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 921c659de8..b6a97b5da7 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -55,6 +55,30 @@ 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 + 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, system.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 7ab652c82a..3ca425fbce 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 From 976fb18a8f99adb9ccec5a248fcf36be7d07388f Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Sun, 23 Mar 2014 18:30:54 -0400 Subject: [PATCH 2/4] made the default comparator for lowerBound unqualified, so the user can customize via two phase lookup --- lib/pure/algorithm.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index b6a97b5da7..fb0ba5355f 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -78,7 +78,7 @@ proc lowerBound*[T](a: openarray[T], key: T, cmp: proc(x,y: T): int {.closure.}) else: count = step -proc lowerBound*[T](a: openarray[T], key: T): int = lowerBound(a, key, system.cmp[T]) +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) = From cabc5c80d36bc515ffbc6787995aac7886cdcfc6 Mon Sep 17 00:00:00 2001 From: Jason Livesay Date: Wed, 26 Mar 2014 18:54:34 -0700 Subject: [PATCH 3/4] Calling randomize() again within 1 second will now provide a different seed --- lib/pure/math.nim | 4 +++- tests/stdlib/tmath.nim | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 062cfae252..94570fc681 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -20,6 +20,8 @@ when defined(Posix) and not defined(haiku): {.passl: "-lm".} +import times + const PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) E* = 2.71828182845904523536028747 ## Euler's number @@ -201,7 +203,7 @@ when not defined(JS): result = drand48() * max proc randomize() = - randomize(gettime(nil)) + randomize(cast[int](epochTime())) proc randomize(seed: int) = srand(cint(seed)) diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index a86a3b84ce..fc9486093d 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -23,6 +23,13 @@ suite "random int": rand = random(100..1000) check rand < 1000 check rand >= 100 + test "randomize() again gives new numbers": + randomize() + var rand1 = random(1000000) + randomize() + var rand2 = random(1000000) + check rand1 != rand2 + suite "random float": test "there might be some randomness": @@ -45,3 +52,10 @@ suite "random float": rand = random(100.0..1000.0) check rand < 1000.0 check rand >= 100.0 + test "randomize() again gives new numbers": + randomize() + var rand1:float = random(1000000.0) + randomize() + var rand2:float = random(1000000.0) + check rand1 != rand2 + From 491291ae24fe5901f4be918cbce2d6c21a0ae0e9 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Thu, 27 Mar 2014 00:21:19 -0400 Subject: [PATCH 4/4] added usage example for lower bound --- lib/pure/algorithm.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index fb0ba5355f..49d1ac972b 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -63,6 +63,11 @@ proc lowerBound*[T](a: openarray[T], key: T, cmp: proc(x,y: T): int {.closure.}) ## ## `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