algorithm.nim 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module implements some common generic algorithms.
  10. type
  11. SortOrder* = enum
  12. Descending, Ascending
  13. proc `*`*(x: int, order: SortOrder): int {.inline.} =
  14. ## flips ``x`` if ``order == Descending``.
  15. ## If ``order == Ascending`` then ``x`` is returned.
  16. ##
  17. ## ``x`` is supposed to be the result of a comparator, i.e.
  18. ## | ``< 0`` for *less than*,
  19. ## | ``== 0`` for *equal*,
  20. ## | ``> 0`` for *greater than*.
  21. var y = order.ord - 1
  22. result = (x xor y) - y
  23. template fillImpl[T](a: var openArray[T], first, last: int, value: T) =
  24. var x = first
  25. while x <= last:
  26. a[x] = value
  27. inc(x)
  28. proc fill*[T](a: var openArray[T], first, last: Natural, value: T) =
  29. ## fills the slice ``a[first..last]`` with ``value``.
  30. runnableExamples:
  31. var a: array[6, int]
  32. a.fill(1, 3, 9)
  33. doAssert a == [0, 9, 9, 9, 0, 0]
  34. fillImpl(a, first, last, value)
  35. proc fill*[T](a: var openArray[T], value: T) =
  36. ## fills the container ``a`` with ``value``.
  37. runnableExamples:
  38. var a: array[6, int]
  39. a.fill(9)
  40. doAssert a == [9, 9, 9, 9, 9, 9]
  41. fillImpl(a, 0, a.high, value)
  42. proc reverse*[T](a: var openArray[T], first, last: Natural) =
  43. ## reverses the slice ``a[first..last]``.
  44. runnableExamples:
  45. var a = [1, 2, 3, 4, 5, 6]
  46. a.reverse(1, 3)
  47. doAssert a == [1, 4, 3, 2, 5, 6]
  48. var x = first
  49. var y = last
  50. while x < y:
  51. swap(a[x], a[y])
  52. dec(y)
  53. inc(x)
  54. proc reverse*[T](a: var openArray[T]) =
  55. ## reverses the contents of the container ``a``.
  56. runnableExamples:
  57. var a = [1, 2, 3, 4, 5, 6]
  58. a.reverse()
  59. doAssert a == [6, 5, 4, 3, 2, 1]
  60. reverse(a, 0, max(0, a.high))
  61. proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] =
  62. ## returns the reverse of the slice ``a[first..last]``.
  63. runnableExamples:
  64. let
  65. a = [1, 2, 3, 4, 5, 6]
  66. b = reversed(a, 1, 3)
  67. doAssert b == @[4, 3, 2]
  68. assert last >= first-1
  69. var i = last - first
  70. var x = first.int
  71. result = newSeq[T](i + 1)
  72. while i >= 0:
  73. result[i] = a[x]
  74. dec(i)
  75. inc(x)
  76. proc reversed*[T](a: openArray[T]): seq[T] =
  77. ## returns the reverse of the container ``a``.
  78. runnableExamples:
  79. let
  80. a = [1, 2, 3, 4, 5, 6]
  81. b = reversed(a)
  82. doAssert b == @[6, 5, 4, 3, 2, 1]
  83. reversed(a, 0, a.high)
  84. proc binarySearch*[T, K](a: openArray[T], key: K,
  85. cmp: proc (x: T, y: K): int {.closure.}): int =
  86. ## Binary search for ``key`` in ``a``. Returns -1 if not found.
  87. ##
  88. ## ``cmp`` is the comparator function to use, the expected return values are
  89. ## the same as that of system.cmp.
  90. if a.len == 0:
  91. return -1
  92. let len = a.len
  93. if len == 1:
  94. if cmp(a[0], key) == 0:
  95. return 0
  96. else:
  97. return -1
  98. if (len and (len - 1)) == 0:
  99. # when `len` is a power of 2, a faster shr can be used.
  100. var step = len shr 1
  101. var cmpRes: int
  102. while step > 0:
  103. let i = result or step
  104. cmpRes = cmp(a[i], key)
  105. if cmpRes == 0:
  106. return i
  107. if cmpRes < 1:
  108. result = i
  109. step = step shr 1
  110. if cmp(a[result], key) != 0: result = -1
  111. else:
  112. var b = len
  113. var cmpRes: int
  114. while result < b:
  115. var mid = (result + b) shr 1
  116. cmpRes = cmp(a[mid], key)
  117. if cmpRes == 0:
  118. return mid
  119. if cmpRes < 0:
  120. result = mid + 1
  121. else:
  122. b = mid
  123. if result >= len or cmp(a[result], key) != 0: result = -1
  124. proc binarySearch*[T](a: openArray[T], key: T): int =
  125. ## Binary search for ``key`` in ``a``. Returns -1 if not found.
  126. binarySearch(a, key, cmp[T])
  127. proc smartBinarySearch*[T](a: openArray[T], key: T): int {.deprecated.} =
  128. ## **Deprecated since version 0.18.1**; Use ``binarySearch`` instead.
  129. binarySearch(a, key, cmp[T])
  130. const
  131. onlySafeCode = true
  132. proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
  133. ## returns a position to the first element in the ``a`` that is greater than
  134. ## ``key``, or last if no such element is found.
  135. ## In other words if you have a sorted sequence and you call
  136. ## ``insert(thing, elm, lowerBound(thing, elm))``
  137. ## the sequence will still be sorted.
  138. ##
  139. ## The first version uses ``cmp`` to compare the elements.
  140. ## The expected return values are the same as that of ``system.cmp``.
  141. ## The second version uses the default comparison function ``cmp``.
  142. ##
  143. ## .. code-block:: nim
  144. ##
  145. ## var arr = @[1,2,3,5,6,7,8,9]
  146. ## arr.insert(4, arr.lowerBound(4))
  147. ## # after running the above arr is `[1,2,3,4,5,6,7,8,9]`
  148. result = a.low
  149. var count = a.high - a.low + 1
  150. var step, pos: int
  151. while count != 0:
  152. step = count shr 1
  153. pos = result + step
  154. if cmp(a[pos], key) < 0:
  155. result = pos + 1
  156. count -= step + 1
  157. else:
  158. count = step
  159. proc lowerBound*[T](a: openArray[T], key: T): int = lowerBound(a, key, cmp[T])
  160. proc upperBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
  161. ## returns a position to the first element in the ``a`` that is not less
  162. ## (i.e. greater or equal to) than ``key``, or last if no such element is found.
  163. ## In other words if you have a sorted sequence and you call
  164. ## ``insert(thing, elm, upperBound(thing, elm))``
  165. ## the sequence will still be sorted.
  166. ##
  167. ## The first version uses ``cmp`` to compare the elements. The expected
  168. ## return values are the same as that of ``system.cmp``.
  169. ## The second version uses the default comparison function ``cmp``.
  170. ##
  171. ## .. code-block:: nim
  172. ##
  173. ## var arr = @[1,2,3,4,6,7,8,9]
  174. ## arr.insert(5, arr.upperBound(4))
  175. ## # after running the above arr is `[1,2,3,4,5,6,7,8,9]`
  176. result = a.low
  177. var count = a.high - a.low + 1
  178. var step, pos: int
  179. while count != 0:
  180. step = count shr 1
  181. pos = result + step
  182. if cmp(a[pos], key) <= 0:
  183. result = pos + 1
  184. count -= step + 1
  185. else:
  186. count = step
  187. proc upperBound*[T](a: openArray[T], key: T): int = upperBound(a, key, cmp[T])
  188. template `<-` (a, b) =
  189. when false:
  190. a = b
  191. elif onlySafeCode:
  192. shallowCopy(a, b)
  193. else:
  194. copyMem(addr(a), addr(b), sizeof(T))
  195. proc merge[T](a, b: var openArray[T], lo, m, hi: int,
  196. cmp: proc (x, y: T): int {.closure.}, order: SortOrder) =
  197. # optimization: If max(left) <= min(right) there is nothing to do!
  198. # 1 2 3 4 ## 5 6 7 8
  199. # -> O(n) for sorted arrays.
  200. # On random data this safes up to 40% of merge calls
  201. if cmp(a[m], a[m+1]) * order <= 0: return
  202. var j = lo
  203. # copy a[j..m] into b:
  204. assert j <= m
  205. when onlySafeCode:
  206. var bb = 0
  207. while j <= m:
  208. b[bb] <- a[j]
  209. inc(bb)
  210. inc(j)
  211. else:
  212. copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1))
  213. j = m+1
  214. var i = 0
  215. var k = lo
  216. # copy proper element back:
  217. while k < j and j <= hi:
  218. if cmp(b[i], a[j]) * order <= 0:
  219. a[k] <- b[i]
  220. inc(i)
  221. else:
  222. a[k] <- a[j]
  223. inc(j)
  224. inc(k)
  225. # copy rest of b:
  226. when onlySafeCode:
  227. while k < j:
  228. a[k] <- b[i]
  229. inc(k)
  230. inc(i)
  231. else:
  232. if k < j: copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k))
  233. func sort*[T](a: var openArray[T],
  234. cmp: proc (x, y: T): int {.closure.},
  235. order = SortOrder.Ascending) =
  236. ## Default Nim sort (an implementation of merge sort). The sorting
  237. ## is guaranteed to be stable and the worst case is guaranteed to
  238. ## be O(n log n).
  239. ## The current implementation uses an iterative
  240. ## mergesort to achieve this. It uses a temporary sequence of
  241. ## length ``a.len div 2``. If you do not wish to provide your own
  242. ## ``cmp``, you may use ``system.cmp`` or instead call the overloaded
  243. ## version of ``sort``, which uses ``system.cmp``.
  244. ##
  245. ## .. code-block:: nim
  246. ##
  247. ## sort(myIntArray, system.cmp[int])
  248. ##
  249. ## # do not use cmp[string] here as we want to use the specialized
  250. ## # overload:
  251. ## sort(myStrArray, system.cmp)
  252. ##
  253. ## You can inline adhoc comparison procs with the `do notation
  254. ## <manual.html#procedures-do-notation>`_. Example:
  255. ##
  256. ## .. code-block:: nim
  257. ##
  258. ## people.sort do (x, y: Person) -> int:
  259. ## result = cmp(x.surname, y.surname)
  260. ## if result == 0:
  261. ## result = cmp(x.name, y.name)
  262. var n = a.len
  263. var b: seq[T]
  264. newSeq(b, n div 2)
  265. var s = 1
  266. while s < n:
  267. var m = n-1-s
  268. while m >= 0:
  269. merge(a, b, max(m-s+1, 0), m, m+s, cmp, order)
  270. dec(m, s*2)
  271. s = s*2
  272. proc sort*[T](a: var openArray[T], order = SortOrder.Ascending) = sort[T](a, system.cmp[T], order)
  273. ## Shortcut version of ``sort`` that uses ``system.cmp[T]`` as the comparison function.
  274. proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
  275. order = SortOrder.Ascending): seq[T] =
  276. ## returns ``a`` sorted by ``cmp`` in the specified ``order``.
  277. runnableExamples:
  278. let
  279. a = [2, 3, 1, 5, 4]
  280. b = sorted(a, system.cmp)
  281. c = sorted(a, system.cmp, Descending)
  282. doAssert b == @[1, 2, 3, 4, 5]
  283. doAssert c == @[5, 4, 3, 2, 1]
  284. result = newSeq[T](a.len)
  285. for i in 0 .. a.high:
  286. result[i] = a[i]
  287. sort(result, cmp, order)
  288. proc sorted*[T](a: openArray[T], order = SortOrder.Ascending): seq[T] =
  289. ## Shortcut version of ``sorted`` that uses ``system.cmp[T]`` as the comparison function.
  290. sorted[T](a, system.cmp[T], order)
  291. template sortedByIt*(seq1, op: untyped): untyped =
  292. ## Convenience template around the ``sorted`` proc to reduce typing.
  293. ##
  294. ## The template injects the ``it`` variable which you can use directly in an
  295. ## expression. Example:
  296. ##
  297. ## .. code-block:: nim
  298. ##
  299. ## type Person = tuple[name: string, age: int]
  300. ## var
  301. ## p1: Person = (name: "p1", age: 60)
  302. ## p2: Person = (name: "p2", age: 20)
  303. ## p3: Person = (name: "p3", age: 30)
  304. ## p4: Person = (name: "p4", age: 30)
  305. ## people = @[p1,p2,p4,p3]
  306. ##
  307. ## echo people.sortedByIt(it.name)
  308. ##
  309. ## Because the underlying ``cmp()`` is defined for tuples you can do
  310. ## a nested sort like in the following example:
  311. ##
  312. ## .. code-block:: nim
  313. ##
  314. ## echo people.sortedByIt((it.age, it.name))
  315. ##
  316. var result = sorted(seq1, proc(x, y: type(seq1[0])): int =
  317. var it {.inject.} = x
  318. let a = op
  319. it = y
  320. let b = op
  321. result = cmp(a, b))
  322. result
  323. func isSorted*[T](a: openArray[T],
  324. cmp: proc(x, y: T): int {.closure.},
  325. order = SortOrder.Ascending): bool =
  326. ## checks to see whether ``a`` is already sorted in ``order``
  327. ## using ``cmp`` for the comparison. Parameters identical
  328. ## to ``sort``.
  329. result = true
  330. for i in 0..<len(a)-1:
  331. if cmp(a[i],a[i+1]) * order > 0:
  332. return false
  333. proc isSorted*[T](a: openarray[T], order = SortOrder.Ascending): bool =
  334. ## Shortcut version of ``isSorted`` that uses ``system.cmp[T]`` as the comparison function.
  335. isSorted(a, system.cmp[T], order)
  336. proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
  337. ## produces the Cartesian product of the array. Warning: complexity
  338. ## may explode.
  339. result = newSeq[seq[T]]()
  340. if x.len == 0:
  341. return
  342. if x.len == 1:
  343. result = @x
  344. return
  345. var
  346. indexes = newSeq[int](x.len)
  347. initial = newSeq[int](x.len)
  348. index = 0
  349. var next = newSeq[T]()
  350. next.setLen(x.len)
  351. for i in 0..(x.len-1):
  352. if len(x[i]) == 0: return
  353. initial[i] = len(x[i])-1
  354. indexes = initial
  355. while true:
  356. while indexes[index] == -1:
  357. indexes[index] = initial[index]
  358. index += 1
  359. if index == x.len: return
  360. indexes[index] -= 1
  361. for ni, i in indexes:
  362. next[ni] = x[ni][i]
  363. var res: seq[T]
  364. shallowCopy(res, next)
  365. result.add(res)
  366. index = 0
  367. indexes[index] -= 1
  368. proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} =
  369. ## calculates the next lexicographic permutation, directly modifying ``x``.
  370. ## The result is whether a permutation happened, otherwise we have reached
  371. ## the last-ordered permutation.
  372. ##
  373. ## .. code-block:: nim
  374. ##
  375. ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  376. ## v.nextPermutation()
  377. ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
  378. if x.len < 2:
  379. return false
  380. var i = x.high
  381. while i > 0 and x[i-1] >= x[i]:
  382. dec i
  383. if i == 0:
  384. return false
  385. var j = x.high
  386. while j >= i and x[j] <= x[i-1]:
  387. dec j
  388. swap x[j], x[i-1]
  389. x.reverse(i, x.high)
  390. result = true
  391. proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} =
  392. ## calculates the previous lexicographic permutation, directly modifying
  393. ## ``x``. The result is whether a permutation happened, otherwise we have
  394. ## reached the first-ordered permutation.
  395. ##
  396. ## .. code-block:: nim
  397. ##
  398. ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
  399. ## v.prevPermutation()
  400. ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  401. if x.len < 2:
  402. return false
  403. var i = x.high
  404. while i > 0 and x[i-1] <= x[i]:
  405. dec i
  406. if i == 0:
  407. return false
  408. x.reverse(i, x.high)
  409. var j = x.high
  410. while j >= i and x[j-1] < x[i-1]:
  411. dec j
  412. swap x[i-1], x[j]
  413. result = true
  414. when isMainModule:
  415. # Tests for lowerBound
  416. var arr = @[1,2,3,5,6,7,8,9]
  417. assert arr.lowerBound(0) == 0
  418. assert arr.lowerBound(4) == 3
  419. assert arr.lowerBound(5) == 3
  420. assert arr.lowerBound(10) == 8
  421. arr = @[1,5,10]
  422. assert arr.lowerBound(4) == 1
  423. assert arr.lowerBound(5) == 1
  424. assert arr.lowerBound(6) == 2
  425. # Tests for isSorted
  426. var srt1 = [1,2,3,4,4,4,4,5]
  427. var srt2 = ["iello","hello"]
  428. var srt3 = [1.0,1.0,1.0]
  429. var srt4: seq[int]
  430. assert srt1.isSorted(cmp) == true
  431. assert srt2.isSorted(cmp) == false
  432. assert srt3.isSorted(cmp) == true
  433. assert srt4.isSorted(cmp) == true
  434. var srtseq = newSeq[int]()
  435. assert srtseq.isSorted(cmp) == true
  436. # Tests for reversed
  437. var arr1 = @[0,1,2,3,4]
  438. assert arr1.reversed() == @[4,3,2,1,0]
  439. for i in 0 .. high(arr1):
  440. assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
  441. assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
  442. proc rotateInternal[T](arg: var openarray[T]; first, middle, last: int): int =
  443. ## A port of std::rotate from c++. Ported from `this reference <http://www.cplusplus.com/reference/algorithm/rotate/>`_.
  444. result = first + last - middle
  445. if first == middle or middle == last:
  446. return
  447. assert first < middle
  448. assert middle < last
  449. # m prefix for mutable
  450. var
  451. mFirst = first
  452. mMiddle = middle
  453. next = middle
  454. swap(arg[mFirst], arg[next])
  455. mFirst += 1
  456. next += 1
  457. if mFirst == mMiddle:
  458. mMiddle = next
  459. while next != last:
  460. swap(arg[mFirst], arg[next])
  461. mFirst += 1
  462. next += 1
  463. if mFirst == mMiddle:
  464. mMiddle = next
  465. next = mMiddle
  466. while next != last:
  467. swap(arg[mFirst], arg[next])
  468. mFirst += 1
  469. next += 1
  470. if mFirst == mMiddle:
  471. mMiddle = next
  472. elif next == last:
  473. next = mMiddle
  474. proc rotatedInternal[T](arg: openarray[T]; first, middle, last: int): seq[T] =
  475. result = newSeq[T](arg.len)
  476. for i in 0 ..< first:
  477. result[i] = arg[i]
  478. let N = last - middle
  479. let M = middle - first
  480. for i in 0 ..< N:
  481. result[first+i] = arg[middle+i]
  482. for i in 0 ..< M:
  483. result[first+N+i] = arg[first+i]
  484. for i in last ..< arg.len:
  485. result[i] = arg[i]
  486. proc rotateLeft*[T](arg: var openarray[T]; slice: HSlice[int, int]; dist: int): int {.discardable.} =
  487. ## performs a left rotation on a range of elements. If you want to rotate
  488. ## right, use a negative ``dist``. Specifically, ``rotateLeft`` rotates
  489. ## the elements at ``slice`` by ``dist`` positions.
  490. ##
  491. ## | The element at index ``slice.a + dist`` will be at index ``slice.a``.
  492. ## | The element at index ``slice.b`` will be at ``slice.a + dist -1``.
  493. ## | The element at index ``slice.a`` will be at ``slice.b + 1 - dist``.
  494. ## | The element at index ``slice.a + dist - 1`` will be at ``slice.b``.
  495. ##
  496. ## Elements outside of ``slice`` will be left unchanged.
  497. ## The time complexity is linear to ``slice.b - slice.a + 1``.
  498. ##
  499. ## ``slice``
  500. ## The indices of the element range that should be rotated.
  501. ##
  502. ## ``dist``
  503. ## The distance in amount of elements that the data should be rotated.
  504. ## Can be negative, can be any number.
  505. ##
  506. ## .. code-block:: nim
  507. ##
  508. ## var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  509. ## list.rotateLeft(1 .. 8, 3)
  510. ## doAssert list == [0, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10]
  511. let sliceLen = slice.b + 1 - slice.a
  512. let distLeft = ((dist mod sliceLen) + sliceLen) mod sliceLen
  513. arg.rotateInternal(slice.a, slice.a+distLeft, slice.b + 1)
  514. proc rotateLeft*[T](arg: var openarray[T]; dist: int): int {.discardable.} =
  515. ## Default arguments for slice, so that this procedure operates on the entire
  516. ## ``arg``, and not just on a part of it.
  517. runnableExamples:
  518. var a = [1, 2, 3, 4, 5]
  519. a.rotateLeft(2)
  520. doAssert a == [3, 4, 5, 1, 2]
  521. let arglen = arg.len
  522. let distLeft = ((dist mod arglen) + arglen) mod arglen
  523. arg.rotateInternal(0, distLeft, arglen)
  524. proc rotatedLeft*[T](arg: openarray[T]; slice: HSlice[int, int], dist: int): seq[T] =
  525. ## Same as ``rotateLeft``, just with the difference that it does
  526. ## not modify the argument. It creates a new ``seq`` instead.
  527. let sliceLen = slice.b + 1 - slice.a
  528. let distLeft = ((dist mod sliceLen) + sliceLen) mod sliceLen
  529. arg.rotatedInternal(slice.a, slice.a+distLeft, slice.b+1)
  530. proc rotatedLeft*[T](arg: openarray[T]; dist: int): seq[T] =
  531. ## Same as ``rotateLeft``, just with the difference that it does
  532. ## not modify the argument. It creates a new ``seq`` instead.
  533. let arglen = arg.len
  534. let distLeft = ((dist mod arglen) + arglen) mod arglen
  535. arg.rotatedInternal(0, distLeft, arg.len)
  536. when isMainModule:
  537. var list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  538. let list2 = list.rotatedLeft(1 ..< 9, 3)
  539. let expected = [0, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10]
  540. doAssert list.rotateLeft(1 ..< 9, 3) == 6
  541. doAssert list == expected
  542. doAssert list2 == @expected
  543. var s0,s1,s2,s3,s4,s5 = "xxxabcdefgxxx"
  544. doAssert s0.rotateLeft(3 ..< 10, 3) == 7
  545. doAssert s0 == "xxxdefgabcxxx"
  546. doAssert s1.rotateLeft(3 ..< 10, 2) == 8
  547. doAssert s1 == "xxxcdefgabxxx"
  548. doAssert s2.rotateLeft(3 ..< 10, 4) == 6
  549. doAssert s2 == "xxxefgabcdxxx"
  550. doAssert s3.rotateLeft(3 ..< 10, -3) == 6
  551. doAssert s3 == "xxxefgabcdxxx"
  552. doAssert s4.rotateLeft(3 ..< 10, -10) == 6
  553. doAssert s4 == "xxxefgabcdxxx"
  554. doAssert s5.rotateLeft(3 ..< 10, 11) == 6
  555. doAssert s5 == "xxxefgabcdxxx"
  556. block product:
  557. doAssert product(newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input"
  558. doAssert product(@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input"
  559. doAssert product(@[@[1,2]]) == @[@[1,2]], "a simple case of one element"
  560. doAssert product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]], "two elements"
  561. 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"
  562. doAssert product(@[@[1,2], @[]]) == newSeq[seq[int]](), "two elements, but one empty"
  563. block lowerBound:
  564. doAssert lowerBound([1,2,4], 3, system.cmp[int]) == 2
  565. doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4
  566. doAssert lowerBound([1,2,3,10], 11) == 4
  567. block upperBound:
  568. doAssert upperBound([1,2,4], 3, system.cmp[int]) == 2
  569. doAssert upperBound([1,2,2,3], 3, system.cmp[int]) == 4
  570. doAssert upperBound([1,2,3,5], 3) == 3
  571. block fillEmptySeq:
  572. var s = newSeq[int]()
  573. s.fill(0)
  574. block testBinarySearch:
  575. var noData: seq[int]
  576. doAssert binarySearch(noData, 7) == -1
  577. let oneData = @[1]
  578. doAssert binarySearch(oneData, 1) == 0
  579. doAssert binarySearch(onedata, 7) == -1
  580. let someData = @[1,3,4,7]
  581. doAssert binarySearch(someData, 1) == 0
  582. doAssert binarySearch(somedata, 7) == 3
  583. doAssert binarySearch(someData, -1) == -1
  584. doAssert binarySearch(someData, 5) == -1
  585. doAssert binarySearch(someData, 13) == -1
  586. let moreData = @[1,3,5,7,4711]
  587. doAssert binarySearch(moreData, -1) == -1
  588. doAssert binarySearch(moreData, 1) == 0
  589. doAssert binarySearch(moreData, 5) == 2
  590. doAssert binarySearch(moreData, 6) == -1
  591. doAssert binarySearch(moreData, 4711) == 4
  592. doAssert binarySearch(moreData, 4712) == -1