diff options
author | def <dennis@felsin9.de> | 2015-02-01 18:29:01 +0100 |
---|---|---|
committer | def <dennis@felsin9.de> | 2015-02-01 18:29:01 +0100 |
commit | 1ae4d535cd8ed6b797cf0525eaab9e0c889e0c6d (patch) | |
tree | eaf2460ac515a4e58e87d328cb2f948a7c1f35e6 /lib | |
parent | 903ca78289dc0460e07bd449a972a4d203d9a09b (diff) | |
download | Nim-1ae4d535cd8ed6b797cf0525eaab9e0c889e0c6d.tar.gz |
Add nextPermutation and prevPermutation
Fits best into algorithm module I guess. These are the most general ways, an iterator could easily be implemented from this. Same algorithm as in Rust: http://web.mit.edu/rust-lang_v0.11/doc/src/collections/var/tmp/alexp/rust/rust-0.11.0/src/libcollections/slice.rs.html#644
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/algorithm.nim | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 0358a9a81..20bfc5c7c 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -220,3 +220,62 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] = result.add(res) index = 0 indexes[index] -=1 + +proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} = + ## Calculates the next lexicographic permutation, directly modifying ``x``. + ## The result is whether a permutation happened, otherwise we have reached + ## the last-ordered permutation. + ## + ## .. code-block:: nim + ## + ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + ## v.nextPermutation() + ## echo v + if x.len < 2: + return false + + var i = x.high + while i > 0 and x[i-1] >= x[i]: + dec i + + if i == 0: + return false + + var j = x.high + while j >= i and x[j] <= x[i-1]: + dec j + + swap x[j], x[i-1] + x.reverse(i, x.high) + + result = true + +proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} = + ## Calculates the previous lexicographic permutation, directly modifying + ## ``x``. The result is whether a permutation happened, otherwise we have + ## reached the first-ordered permutation. + ## + ## .. code-block:: nim + ## + ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8] + ## v.prevPermutation() + ## echo v + if x.len < 2: + return false + + var i = x.high + while i > 0 and x[i-1] <= x[i]: + dec i + + if i == 0: + return false + + x.reverse(i, x.high) + + var j = x.high + while j >= i and x[j-1] < x[i-1]: + dec j + + swap x[i-1], x[j] + + result = true |