diff options
author | Arne Döring <arne.doering@gmx.net> | 2017-07-27 18:22:59 +0200 |
---|---|---|
committer | Arne Döring <arne.doering@gmx.net> | 2017-07-27 18:22:59 +0200 |
commit | 316886542b0a7b9143e0ba96ef93b93a9caadbe6 (patch) | |
tree | 4cd490997206250cfdf338ff6e29134a37ad5412 /lib | |
parent | 409854c91379610853103cabc3ec29c04fbd13e0 (diff) | |
download | Nim-316886542b0a7b9143e0ba96ef93b93a9caadbe6.tar.gz |
allow a negative distance argument. Improved documentation.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/algorithm.nim | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index ea7752b18..a808b6703 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -425,7 +425,7 @@ proc rotated_internal[T](arg: openarray[T]; first, middle, last: int): seq[T] = result[i] = arg[i] proc rotateLeft*[T](arg: var openarray[T]; slice: Slice[int]; dist: int): int = - ## Performs a left rotation on a range of elements. + ## Performs a left rotation on a range of elements. If you want to rotate right, use a negative ``dist``. ## Specifically, ``rotate`` rotates the elements at ``slice`` by ``dist`` positions.. ## The element at index ``slice.a + dist`` will be at index ``slice.a``. ## The element at index ``slice.b`` will be at ``slice.a + dist -1``. @@ -438,28 +438,36 @@ proc rotateLeft*[T](arg: var openarray[T]; slice: Slice[int]; dist: int): int = ## the indices of the element range that should be rotated. ## ## ``dist`` - ## the distance in amount of elements that the data should be rotated. + ## the distance in amount of elements that the data should be rotated. Can be negative, can be any number. ## ## .. code-block:: nim ## var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ## list.rotateLeft(1 .. 8, 3) ## echo @list # @[0, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10] - arg.rotate_internal(slice.a, slice.a+dist, slice.b + 1) + let sliceLen = slice.b + 1 - slice.a + let distLeft = ((dist mod sliceLen) + sliceLen) mod sliceLen + arg.rotate_internal(slice.a, slice.a+distLeft, slice.b + 1) proc rotateLeft*[T](arg: var openarray[T]; dist: int): int = ## default arguments for slice, so that this procedure operates on the entire ## ``arg``, and not just on a part of it. - arg.rotate_internal(0, dist, arg.len) + let arglen = arg.len + let distLeft = ((dist mod arglen) + arglen) mod arglen + arg.rotate_internal(0, distLeft, arglen) proc rotatedLeft*[T](arg: openarray[T]; slice: Slice[int], dist: int): seq[T] = ## same as ``rotateLeft``, just with the difference that it does ## not modify the argument. It creates a new ``seq`` instead - arg.rotated_internal(slice.a, slice.a+dist, slice.b+1) + let sliceLen = slice.b + 1 - slice.a + let distLeft = ((dist mod sliceLen) + sliceLen) mod sliceLen + arg.rotated_internal(slice.a, slice.a+distLeft, slice.b+1) proc rotatedLeft*[T](arg: openarray[T]; dist: int): seq[T] = ## same as ``rotateLeft``, just with the difference that it does ## not modify the argument. It creates a new ``seq`` instead - arg.rotated_internal(0, dist, arg.len) + let arglen = arg.len + let distLeft = ((dist mod arglen) + arglen) mod arglen + arg.rotated_internal(0, distLeft, arg.len) when isMainModule: var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] @@ -470,11 +478,17 @@ when isMainModule: doAssert list == expected doAssert list2 == @expected - var s0,s1,s2 = "xxxabcdefgxxx" + var s0,s1,s2,s3,s4,s5 = "xxxabcdefgxxx" doAssert s0.rotateLeft(3 ..< 10, 3) == 7 doAssert s0 == "xxxdefgabcxxx" doAssert s1.rotateLeft(3 ..< 10, 2) == 8 doAssert s1 == "xxxcdefgabxxx" doAssert s2.rotateLeft(3 ..< 10, 4) == 6 - doassert s2 == "xxxefgabcdxxx" + doAssert s2 == "xxxefgabcdxxx" + doAssert s3.rotateLeft(3 ..< 10, -3) == 6 + doAssert s3 == "xxxefgabcdxxx" + doAssert s4.rotateLeft(3 ..< 10, -10) == 6 + doAssert s4 == "xxxefgabcdxxx" + doAssert s5.rotateLeft(3 ..< 10, 11) == 6 + doAssert s5 == "xxxefgabcdxxx" |