AdjacentPairs.swift 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Algorithms open source project
  4. //
  5. // Copyright (c) 2021 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. extension Sequence {
  12. /// Creates a sequence of adjacent pairs of elements from this sequence.
  13. ///
  14. /// In the `AdjacentPairsSequence` returned by this method, the elements of
  15. /// the *i*th pair are the *i*th and *(i+1)*th elements of the underlying
  16. /// sequence. The following example uses the `adjacentPairs()` method to
  17. /// iterate over adjacent pairs of integers:
  18. ///
  19. /// for pair in (1...).prefix(5).adjacentPairs() {
  20. /// print(pair)
  21. /// }
  22. /// // Prints "(1, 2)"
  23. /// // Prints "(2, 3)"
  24. /// // Prints "(3, 4)"
  25. /// // Prints "(4, 5)"
  26. @inlinable
  27. public func adjacentPairs() -> AdjacentPairsSequence<Self> {
  28. AdjacentPairsSequence(base: self)
  29. }
  30. }
  31. extension Collection {
  32. /// A collection of adjacent pairs of elements built from an underlying
  33. /// collection.
  34. ///
  35. /// In an `AdjacentPairsCollection`, the elements of the *i*th pair are the
  36. /// *i*th and *(i+1)*th elements of the underlying sequence. The following
  37. /// example uses the `adjacentPairs()` method to iterate over adjacent pairs
  38. /// of integers:
  39. ///
  40. /// for pair in (1...5).adjacentPairs() {
  41. /// print(pair)
  42. /// }
  43. /// // Prints "(1, 2)"
  44. /// // Prints "(2, 3)"
  45. /// // Prints "(3, 4)"
  46. /// // Prints "(4, 5)"
  47. @inlinable
  48. public func adjacentPairs() -> AdjacentPairsCollection<Self> {
  49. AdjacentPairsCollection(base: self)
  50. }
  51. }
  52. /// A sequence of adjacent pairs of elements built from an underlying sequence.
  53. ///
  54. /// Use the `adjacentPairs()` method on a sequence to create an
  55. /// `AdjacentPairsSequence` instance.
  56. public struct AdjacentPairsSequence<Base: Sequence> {
  57. @usableFromInline
  58. internal let base: Base
  59. /// Creates an instance that makes pairs of adjacent elements from `base`.
  60. @inlinable
  61. internal init(base: Base) {
  62. self.base = base
  63. }
  64. }
  65. extension AdjacentPairsSequence {
  66. /// The iterator for an `AdjacentPairsSequence` or `AdjacentPairsCollection`
  67. /// instance.
  68. public struct Iterator {
  69. @usableFromInline
  70. internal var base: Base.Iterator
  71. @usableFromInline
  72. internal var previousElement: Base.Element?
  73. @inlinable
  74. internal init(base: Base.Iterator) {
  75. self.base = base
  76. }
  77. }
  78. }
  79. extension AdjacentPairsSequence.Iterator: IteratorProtocol {
  80. public typealias Element = (Base.Element, Base.Element)
  81. @inlinable
  82. public mutating func next() -> Element? {
  83. if previousElement == nil {
  84. previousElement = base.next()
  85. }
  86. guard let previous = previousElement, let next = base.next() else {
  87. return nil
  88. }
  89. previousElement = next
  90. return (previous, next)
  91. }
  92. }
  93. extension AdjacentPairsSequence: Sequence {
  94. @inlinable
  95. public func makeIterator() -> Iterator {
  96. Iterator(base: base.makeIterator())
  97. }
  98. @inlinable
  99. public var underestimatedCount: Int {
  100. Swift.max(0, base.underestimatedCount - 1)
  101. }
  102. }
  103. extension AdjacentPairsSequence: LazySequenceProtocol
  104. where Base: LazySequenceProtocol {}
  105. /// A collection of adjacent pairs of elements built from an underlying
  106. /// collection.
  107. ///
  108. /// Use the `adjacentPairs()` method on a collection to create an
  109. /// `AdjacentPairsCollection` instance.
  110. public struct AdjacentPairsCollection<Base: Collection> {
  111. @usableFromInline
  112. internal let base: Base
  113. @usableFromInline
  114. internal let secondBaseIndex: Base.Index
  115. @inlinable
  116. internal init(base: Base) {
  117. self.base = base
  118. self.secondBaseIndex = base.isEmpty
  119. ? base.endIndex
  120. : base.index(after: base.startIndex)
  121. }
  122. }
  123. extension AdjacentPairsCollection {
  124. /// A position in an `AdjacentPairsCollection` instance.
  125. public struct Index: Comparable {
  126. @usableFromInline
  127. internal var first: Base.Index
  128. @usableFromInline
  129. internal var second: Base.Index
  130. @inlinable
  131. internal init(first: Base.Index, second: Base.Index) {
  132. self.first = first
  133. self.second = second
  134. }
  135. @inlinable
  136. public static func == (lhs: Index, rhs: Index) -> Bool {
  137. lhs.first == rhs.first
  138. }
  139. @inlinable
  140. public static func < (lhs: Index, rhs: Index) -> Bool {
  141. lhs.first < rhs.first
  142. }
  143. }
  144. }
  145. extension AdjacentPairsCollection: Collection {
  146. @inlinable
  147. public var startIndex: Index {
  148. Index(
  149. first: secondBaseIndex == base.endIndex ? base.endIndex : base.startIndex,
  150. second: secondBaseIndex)
  151. }
  152. @inlinable
  153. public var endIndex: Index {
  154. Index(first: base.endIndex, second: base.endIndex)
  155. }
  156. @inlinable
  157. public subscript(position: Index) -> (Base.Element, Base.Element) {
  158. (base[position.first], base[position.second])
  159. }
  160. @inlinable
  161. public func index(after i: Index) -> Index {
  162. precondition(i != endIndex, "Can't advance beyond endIndex")
  163. let next = base.index(after: i.second)
  164. return next == base.endIndex
  165. ? endIndex
  166. : Index(first: i.second, second: next)
  167. }
  168. @inlinable
  169. public func index(_ i: Index, offsetBy distance: Int) -> Index {
  170. guard distance != 0 else { return i }
  171. guard let result = distance > 0
  172. ? offsetForward(i, by: distance, limitedBy: endIndex)
  173. : offsetBackward(i, by: -distance, limitedBy: startIndex)
  174. else { fatalError("Index out of bounds") }
  175. return result
  176. }
  177. @inlinable
  178. public func index(
  179. _ i: Index, offsetBy distance: Int, limitedBy limit: Index
  180. ) -> Index? {
  181. guard distance != 0 else { return i }
  182. guard limit != i else { return nil }
  183. if distance > 0 {
  184. let limit = limit > i ? limit : endIndex
  185. return offsetForward(i, by: distance, limitedBy: limit)
  186. } else {
  187. let limit = limit < i ? limit : startIndex
  188. return offsetBackward(i, by: -distance, limitedBy: limit)
  189. }
  190. }
  191. @inlinable
  192. internal func offsetForward(
  193. _ i: Index, by distance: Int, limitedBy limit: Index
  194. ) -> Index? {
  195. assert(distance > 0)
  196. assert(limit > i)
  197. guard let newFirst = base.index(i.second, offsetBy: distance - 1, limitedBy: limit.first),
  198. newFirst != base.endIndex
  199. else { return nil }
  200. let newSecond = base.index(after: newFirst)
  201. precondition(newSecond <= base.endIndex, "Can't advance beyond endIndex")
  202. return newSecond == base.endIndex
  203. ? endIndex
  204. : Index(first: newFirst, second: newSecond)
  205. }
  206. @inlinable
  207. internal func offsetBackward(
  208. _ i: Index, by distance: Int, limitedBy limit: Index
  209. ) -> Index? {
  210. assert(distance > 0)
  211. assert(limit < i)
  212. let offset = i == endIndex ? 0 : 1
  213. guard let newSecond = base.index(
  214. i.first,
  215. offsetBy: -(distance - offset),
  216. limitedBy: limit.second)
  217. else { return nil }
  218. let newFirst = base.index(newSecond, offsetBy: -1)
  219. precondition(newFirst >= base.startIndex, "Can't move before startIndex")
  220. return Index(first: newFirst, second: newSecond)
  221. }
  222. @inlinable
  223. public func distance(from start: Index, to end: Index) -> Int {
  224. // While there's a 2-step gap between the `first` base index values in
  225. // `endIndex` and the penultimate index of this collection, the `second`
  226. // base index values are consistently one step apart throughout the
  227. // entire collection.
  228. base.distance(from: start.second, to: end.second)
  229. }
  230. @inlinable
  231. public var count: Int {
  232. Swift.max(0, base.count - 1)
  233. }
  234. }
  235. extension AdjacentPairsCollection: BidirectionalCollection
  236. where Base: BidirectionalCollection
  237. {
  238. @inlinable
  239. public func index(before i: Index) -> Index {
  240. precondition(i != startIndex, "Can't offset before startIndex")
  241. let second = i == endIndex
  242. ? base.index(before: base.endIndex)
  243. : i.first
  244. let first = base.index(before: second)
  245. return Index(first: first, second: second)
  246. }
  247. }
  248. extension AdjacentPairsCollection: RandomAccessCollection
  249. where Base: RandomAccessCollection {}
  250. extension AdjacentPairsCollection: LazySequenceProtocol, LazyCollectionProtocol
  251. where Base: LazySequenceProtocol {}
  252. extension AdjacentPairsCollection.Index: Hashable where Base.Index: Hashable {
  253. @inlinable
  254. public func hash(into hasher: inout Hasher) {
  255. hasher.combine(first)
  256. }
  257. }