tbraces.nim 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. #? braces
  2. #
  3. #
  4. # Nim's Runtime Library
  5. # (c) Copyright 2015 Andreas Rumpf
  6. #
  7. # See the file "copying.txt", included in this
  8. # distribution, for details about the copyright.
  9. #
  10. ## This module implements some common generic algorithms.
  11. type
  12. SortOrder* = enum { ## sort order
  13. Descending, Ascending
  14. }
  15. type(
  16. DummyAlias = int
  17. OtherAlias = distinct char
  18. SomeObject = object of RootObj { ## declaration here
  19. fieldA, fieldB: int
  20. case order: SortOrder {
  21. of Descending {a: string}
  22. of Ascending {b: seq[char]}
  23. }
  24. }
  25. MyConcept = concept x {
  26. x is int
  27. }
  28. )
  29. {.deprecated: [TSortOrder: SortOrder].}
  30. proc `*`*(x: int, order: SortOrder): int @inline {
  31. ## flips `x` if ``order == Descending``;
  32. ## if ``order == Ascending`` then `x` is returned.
  33. ## `x` is supposed to be the result of a comparator, ie ``< 0`` for
  34. ## *less than*, ``== 0`` for *equal*, ``> 0`` for *greater than*.
  35. var y = order.ord - 1
  36. result = (x xor y) - y
  37. }
  38. proc fill*[T](a: var openArray[T], first, last: Natural, value: T) {
  39. ## fills the array ``a[first..last]`` with `value`.
  40. var x = first
  41. while x <= last {
  42. a[x] = value
  43. inc(x)
  44. }
  45. }
  46. proc fill*[T](a: var openArray[T], value: T) {
  47. ## fills the array `a` with `value`.
  48. fill(a, 0, a.high, value)
  49. }
  50. proc reverse*[T](a: var openArray[T], first, last: Natural) {
  51. ## reverses the array ``a[first..last]``.
  52. var x = first
  53. var y = last
  54. while x < y {
  55. swap(a[x], a[y])
  56. dec(y)
  57. inc(x)
  58. }
  59. }
  60. proc reverse*[T](a: var openArray[T]) {
  61. ## reverses the array `a`.
  62. reverse(a, 0, a.high)
  63. }
  64. proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] {
  65. ## returns the reverse of the array `a[first..last]`.
  66. assert last >= first-1
  67. var i = last - first
  68. var x = first.int
  69. result = newSeq[T](i + 1)
  70. while i >= 0 {
  71. result[i] = a[x]
  72. dec(i)
  73. inc(x)
  74. }
  75. }
  76. proc reversed*[T](a: openArray[T]): seq[T] {
  77. ## returns the reverse of the array `a`.
  78. reversed(a, 0, a.high)
  79. }
  80. proc binarySearch*[T](a: openArray[T], key: T): int {
  81. ## binary search for `key` in `a`. Returns -1 if not found.
  82. var b = len(a)
  83. while result < b {
  84. var mid = (result + b) div 2
  85. if a[mid] < key { result = mid + 1 } else { b = mid }
  86. }
  87. if result >= len(a) or a[result] != key { result = -1 }
  88. }
  89. proc smartBinarySearch*[T](a: openArray[T], key: T): int {
  90. ## ``a.len`` must be a power of 2 for this to work.
  91. var step = a.len div 2
  92. while step > 0 {
  93. if a[result or step] <= key { result = result or step }
  94. step = step shr 1
  95. }
  96. if a[result] != key { result = -1 }
  97. }
  98. const (
  99. onlySafeCode = true
  100. )
  101. proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int @closure): int {
  102. ## same as binarySearch except that if key is not in `a` then this
  103. ## returns the location where `key` would be if it were. In other
  104. ## words if you have a sorted sequence and you call
  105. ## insert(thing, elm, lowerBound(thing, elm))
  106. ## the sequence will still be sorted.
  107. ##
  108. ## `cmp` is the comparator function to use, the expected return values are
  109. ## the same as that of system.cmp.
  110. ##
  111. ## example::
  112. ##
  113. ## var arr = @[1,2,3,5,6,7,8,9]
  114. ## arr.insert(4, arr.lowerBound(4))
  115. ## # after running the above arr is `[1,2,3,4,5,6,7,8,9]`
  116. result = a.low
  117. var count = a.high - a.low + 1
  118. var step, pos: int
  119. while count != 0 {
  120. step = count div 2
  121. pos = result + step
  122. if cmp(a[pos], key) < 0 {
  123. result = pos + 1
  124. count -= step + 1
  125. } else {
  126. count = step
  127. }
  128. }
  129. }
  130. proc lowerBound*[T](a: openArray[T], key: T): int { lowerBound(a, key, cmp[T]) }
  131. proc merge[T](a, b: var openArray[T], lo, m, hi: int,
  132. cmp: proc (x, y: T): int @closure, order: SortOrder) {
  133. template `<-` (a, b) {
  134. when false {
  135. a = b
  136. } elif onlySafeCode {
  137. shallowCopy(a, b)
  138. } else {
  139. copyMem(addr(a), addr(b), sizeof(T))
  140. }
  141. }
  142. # optimization: If max(left) <= min(right) there is nothing to do!
  143. # 1 2 3 4 ## 5 6 7 8
  144. # -> O(n) for sorted arrays.
  145. # On random data this safes up to 40% of merge calls
  146. if cmp(a[m], a[m+1]) * order <= 0 { return }
  147. var j = lo
  148. # copy a[j..m] into b:
  149. assert j <= m
  150. when onlySafeCode {
  151. var bb = 0
  152. while j <= m {
  153. b[bb] <- a[j]
  154. inc(bb)
  155. inc(j)
  156. }
  157. } else {
  158. copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1))
  159. j = m+1
  160. }
  161. var i = 0
  162. var k = lo
  163. # copy proper element back:
  164. while k < j and j <= hi {
  165. if cmp(b[i], a[j]) * order <= 0 {
  166. a[k] <- b[i]
  167. inc(i)
  168. } else {
  169. a[k] <- a[j]
  170. inc(j)
  171. }
  172. inc(k)
  173. }
  174. # copy rest of b:
  175. when onlySafeCode {
  176. while k < j {
  177. a[k] <- b[i]
  178. inc(k)
  179. inc(i)
  180. }
  181. } else {
  182. if k < j { copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k)) }
  183. }
  184. }
  185. proc sort*[T](a: var openArray[T],
  186. cmp: proc (x, y: T): int @closure,
  187. order = SortOrder.Ascending) {
  188. ## Default Nim sort (an implementation of merge sort). The sorting
  189. ## is guaranteed to be stable and the worst case is guaranteed to
  190. ## be O(n log n).
  191. ## The current implementation uses an iterative
  192. ## mergesort to achieve this. It uses a temporary sequence of
  193. ## length ``a.len div 2``. Currently Nim does not support a
  194. ## sensible default argument for ``cmp``, so you have to provide one
  195. ## of your own. However, the ``system.cmp`` procs can be used:
  196. ##
  197. ## .. code-block:: nim
  198. ##
  199. ## sort(myIntArray, system.cmp[int])
  200. ##
  201. ## # do not use cmp[string] here as we want to use the specialized
  202. ## # overload:
  203. ## sort(myStrArray, system.cmp)
  204. ##
  205. ## You can inline adhoc comparison procs with the `do notation
  206. ## <manual.html#procedures-do-notation>`_. Example:
  207. ##
  208. ## .. code-block:: nim
  209. ##
  210. ## people.sort do (x, y: Person) -> int:
  211. ## result = cmp(x.surname, y.surname)
  212. ## if result == 0:
  213. ## result = cmp(x.name, y.name)
  214. var n = a.len
  215. var b: seq[T]
  216. newSeq(b, n div 2)
  217. var s = 1
  218. while s < n {
  219. var m = n-1-s
  220. while m >= 0 {
  221. merge(a, b, max(m-s+1, 0), m, m+s, cmp, order)
  222. dec(m, s*2)
  223. }
  224. s = s*2
  225. }
  226. }
  227. proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
  228. order = SortOrder.Ascending): seq[T] {
  229. ## returns `a` sorted by `cmp` in the specified `order`.
  230. result = newSeq[T](a.len)
  231. for i in 0 .. a.high { result[i] = a[i] }
  232. sort(result, cmp, order)
  233. }
  234. template sortedByIt*(seq1, op: untyped): untyped {
  235. ## Convenience template around the ``sorted`` proc to reduce typing.
  236. ##
  237. ## The template injects the ``it`` variable which you can use directly in an
  238. ## expression. Example:
  239. ##
  240. ## .. code-block:: nim
  241. ##
  242. ## type Person = tuple[name: string, age: int]
  243. ## var
  244. ## p1: Person = (name: "p1", age: 60)
  245. ## p2: Person = (name: "p2", age: 20)
  246. ## p3: Person = (name: "p3", age: 30)
  247. ## p4: Person = (name: "p4", age: 30)
  248. ## people = @[p1,p2,p4,p3]
  249. ##
  250. ## echo people.sortedByIt(it.name)
  251. ##
  252. ## Because the underlying ``cmp()`` is defined for tuples you can do
  253. ## a nested sort like in the following example:
  254. ##
  255. ## .. code-block:: nim
  256. ##
  257. ## echo people.sortedByIt((it.age, it.name))
  258. ##
  259. var result = sorted(seq1, proc(x, y: type[seq1[0]]): int {
  260. var it {.inject.} = x
  261. let a = op
  262. it = y
  263. let b = op
  264. result = cmp(a, b)
  265. })
  266. result
  267. }
  268. proc isSorted*[T](a: openarray[T],
  269. cmp: proc(x, y: T): int {.closure.},
  270. order = SortOrder.Ascending): bool {
  271. ## Checks to see whether `a` is already sorted in `order`
  272. ## using `cmp` for the comparison. Parameters identical
  273. ## to `sort`
  274. result = true
  275. for i in 0..<len(a)-1 {
  276. case cmp(a[i],a[i+1]) * order > 0 {
  277. of true { return false }
  278. of false {}
  279. }
  280. }
  281. }
  282. proc product*[T](x: openArray[seq[T]]): seq[seq[T]] {
  283. ## produces the Cartesian product of the array. Warning: complexity
  284. ## may explode.
  285. result = newSeq[seq[T]]()
  286. if x.len == 0 { return }
  287. if x.len == 1 {
  288. result = @x
  289. return
  290. }
  291. var (
  292. indexes = newSeq[int](x.len)
  293. initial = newSeq[int](x.len)
  294. index = 0
  295. )
  296. var next = newSeq[T]()
  297. next.setLen(x.len)
  298. for i in 0..(x.len-1) {
  299. if len(x[i]) == 0 { return }
  300. initial[i] = len(x[i])-1
  301. }
  302. indexes = initial
  303. while true {
  304. while indexes[index] == -1 {
  305. indexes[index] = initial[index]
  306. index += 1
  307. if index == x.len { return }
  308. indexes[index] -= 1
  309. }
  310. for ni, i in indexes {
  311. next[ni] = x[ni][i]
  312. }
  313. var res: seq[T]
  314. shallowCopy(res, next)
  315. result.add(res)
  316. index = 0
  317. indexes[index] -= 1
  318. }
  319. }
  320. proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} {
  321. ## Calculates the next lexicographic permutation, directly modifying ``x``.
  322. ## The result is whether a permutation happened, otherwise we have reached
  323. ## the last-ordered permutation.
  324. ##
  325. ## .. code-block:: nim
  326. ##
  327. ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  328. ## v.nextPermutation()
  329. ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
  330. if x.len < 2 {
  331. return false }
  332. var i = x.high
  333. while i > 0 and x[i-1] >= x[i] { dec i }
  334. if i == 0 { return false }
  335. var j = x.high
  336. while j >= i and x[j] <= x[i-1] { dec j }
  337. swap x[j], x[i-1]
  338. x.reverse(i, x.high)
  339. result = true
  340. }
  341. proc prevPermutation*[T](x: var openarray[T]): bool @discardable {
  342. ## Calculates the previous lexicographic permutation, directly modifying
  343. ## ``x``. The result is whether a permutation happened, otherwise we have
  344. ## reached the first-ordered permutation.
  345. ##
  346. ## .. code-block:: nim
  347. ##
  348. ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
  349. ## v.prevPermutation()
  350. ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  351. if x.len < 2 { return false }
  352. var i = x.high
  353. while i > 0 and x[i-1] <= x[i] {
  354. dec i
  355. }
  356. if i == 0 { return false }
  357. x.reverse(i, x.high)
  358. var j = x.high
  359. while j >= i and x[j-1] < x[i-1] {
  360. dec j
  361. }
  362. swap x[i-1], x[j]
  363. result = true
  364. }
  365. when isMainModule {
  366. # Tests for lowerBound
  367. var arr = @[1,2,3,5,6,7,8,9]
  368. assert arr.lowerBound(0) == 0
  369. assert arr.lowerBound(4) == 3
  370. assert arr.lowerBound(5) == 3
  371. assert arr.lowerBound(10) == 8
  372. arr = @[1,5,10]
  373. try {
  374. assert arr.lowerBound(4) == 1
  375. assert arr.lowerBound(5) == 1
  376. assert arr.lowerBound(6) == 2
  377. } except ValueError {}
  378. # Tests for isSorted
  379. var srt1 = [1,2,3,4,4,4,4,5]
  380. var srt2 = ["iello","hello"]
  381. var srt3 = [1.0,1.0,1.0]
  382. var srt4: seq[int] = @[]
  383. assert srt1.isSorted(cmp) == true
  384. assert srt2.isSorted(cmp) == false
  385. assert srt3.isSorted(cmp) == true
  386. var srtseq = newSeq[int]()
  387. assert srtseq.isSorted(cmp) == true
  388. # Tests for reversed
  389. var arr1 = @[0,1,2,3,4]
  390. assert arr1.reversed() == @[4,3,2,1,0]
  391. for i in 0 .. high(arr1) {
  392. assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
  393. assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
  394. }
  395. }