Chain.swift 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Algorithms open source project
  4. //
  5. // Copyright (c) 2020 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. /// A concatenation of two sequences with the same element type.
  12. public struct Chain2Sequence<Base1: Sequence, Base2: Sequence>
  13. where Base1.Element == Base2.Element
  14. {
  15. /// The first sequence in this chain.
  16. @usableFromInline
  17. internal let base1: Base1
  18. /// The second sequence in this chain.
  19. @usableFromInline
  20. internal let base2: Base2
  21. @inlinable
  22. internal init(base1: Base1, base2: Base2) {
  23. self.base1 = base1
  24. self.base2 = base2
  25. }
  26. }
  27. extension Chain2Sequence: Sequence {
  28. /// The iterator for a `Chain2Sequence` instance.
  29. public struct Iterator: IteratorProtocol {
  30. @usableFromInline
  31. internal var iterator1: Base1.Iterator
  32. @usableFromInline
  33. internal var iterator2: Base2.Iterator
  34. @inlinable
  35. internal init(_ concatenation: Chain2Sequence) {
  36. iterator1 = concatenation.base1.makeIterator()
  37. iterator2 = concatenation.base2.makeIterator()
  38. }
  39. @inlinable
  40. public mutating func next() -> Base1.Element? {
  41. return iterator1.next() ?? iterator2.next()
  42. }
  43. }
  44. @inlinable
  45. public func makeIterator() -> Iterator {
  46. Iterator(self)
  47. }
  48. }
  49. extension Chain2Sequence: Collection where Base1: Collection, Base2: Collection {
  50. /// A position in a `Chain2Sequence` instance.
  51. public struct Index: Comparable {
  52. // The internal index representation, which can either be an index of the
  53. // first collection or the second. The `endIndex` of the first collection
  54. // is not to be used as a value - iterating over indices should go straight
  55. // from the penultimate index of the first collection to the start of the
  56. // second.
  57. @usableFromInline
  58. internal enum Representation: Equatable {
  59. case first(Base1.Index)
  60. case second(Base2.Index)
  61. }
  62. @usableFromInline
  63. internal let position: Representation
  64. /// Creates a new index into the first underlying collection.
  65. @inlinable
  66. internal init(first i: Base1.Index) {
  67. position = .first(i)
  68. }
  69. /// Creates a new index into the second underlying collection.
  70. @inlinable
  71. internal init(second i: Base2.Index) {
  72. position = .second(i)
  73. }
  74. @inlinable
  75. public static func < (lhs: Index, rhs: Index) -> Bool {
  76. switch (lhs.position, rhs.position) {
  77. case (.first, .second):
  78. return true
  79. case (.second, .first):
  80. return false
  81. case let (.first(l), .first(r)):
  82. return l < r
  83. case let (.second(l), .second(r)):
  84. return l < r
  85. }
  86. }
  87. }
  88. /// Converts an index of `Base1` to the corresponding `Index` by mapping
  89. /// `base1.endIndex` to `base2.startIndex`.
  90. @inlinable
  91. internal func normalizeIndex(_ i: Base1.Index) -> Index {
  92. i == base1.endIndex ? Index(second: base2.startIndex) : Index(first: i)
  93. }
  94. @inlinable
  95. public var startIndex: Index {
  96. // if `base1` is empty, this will return `base2.startIndex` - if `base2` is
  97. // also empty, this will correctly equal `base2.endIndex`
  98. normalizeIndex(base1.startIndex)
  99. }
  100. @inlinable
  101. public var endIndex: Index {
  102. Index(second: base2.endIndex)
  103. }
  104. @inlinable
  105. public subscript(i: Index) -> Base1.Element {
  106. switch i.position {
  107. case let .first(i):
  108. return base1[i]
  109. case let .second(i):
  110. return base2[i]
  111. }
  112. }
  113. @inlinable
  114. public func index(after i: Index) -> Index {
  115. switch i.position {
  116. case let .first(i):
  117. assert(i != base1.endIndex)
  118. return normalizeIndex(base1.index(after: i))
  119. case let .second(i):
  120. return Index(second: base2.index(after: i))
  121. }
  122. }
  123. @inlinable
  124. public func index(_ i: Index, offsetBy distance: Int) -> Index {
  125. guard distance != 0 else { return i }
  126. return distance > 0
  127. ? offsetForward(i, by: distance)
  128. : offsetBackward(i, by: -distance)
  129. }
  130. @inlinable
  131. public func index(
  132. _ i: Index,
  133. offsetBy distance: Int,
  134. limitedBy limit: Index
  135. ) -> Index? {
  136. if distance >= 0 {
  137. return limit >= i
  138. ? offsetForward(i, by: distance, limitedBy: limit)
  139. : offsetForward(i, by: distance)
  140. } else {
  141. return limit <= i
  142. ? offsetBackward(i, by: -distance, limitedBy: limit)
  143. : offsetBackward(i, by: -distance)
  144. }
  145. }
  146. @inlinable
  147. internal func offsetForward(_ i: Index, by distance: Int) -> Index {
  148. guard let index = offsetForward(i, by: distance, limitedBy: endIndex)
  149. else { fatalError("Index is out of bounds") }
  150. return index
  151. }
  152. @inlinable
  153. internal func offsetBackward(_ i: Index, by distance: Int) -> Index {
  154. guard let index = offsetBackward(i, by: distance, limitedBy: startIndex)
  155. else { fatalError("Index is out of bounds") }
  156. return index
  157. }
  158. @inlinable
  159. internal func offsetForward(
  160. _ i: Index, by distance: Int, limitedBy limit: Index
  161. ) -> Index? {
  162. assert(distance >= 0)
  163. assert(limit >= i)
  164. switch (i.position, limit.position) {
  165. case let (.first(i), .first(limit)):
  166. return base1.index(i, offsetBy: distance, limitedBy: limit)
  167. .map(Index.init(first:))
  168. case let (.first(i), .second(limit)):
  169. if let j = base1.index(i, offsetBy: distance, limitedBy: base1.endIndex) {
  170. // the offset stays within the bounds of `base1`
  171. return normalizeIndex(j)
  172. } else {
  173. // the offset overflows the bounds of `base1` by `n - d`
  174. let d = base1.distance(from: i, to: base1.endIndex)
  175. return base2.index(base2.startIndex, offsetBy: distance - d, limitedBy: limit)
  176. .map(Index.init(second:))
  177. }
  178. case (.second, .first):
  179. // impossible because `limit >= i`
  180. fatalError()
  181. case let (.second(i), .second(limit)):
  182. return base2.index(i, offsetBy: distance, limitedBy: limit)
  183. .map(Index.init(second:))
  184. }
  185. }
  186. @inlinable
  187. internal func offsetBackward(
  188. _ i: Index, by distance: Int, limitedBy limit: Index
  189. ) -> Index? {
  190. assert(distance >= 0)
  191. assert(limit <= i)
  192. switch (i.position, limit.position) {
  193. case let (.first(i), .first(limit)):
  194. return base1.index(i, offsetBy: -distance, limitedBy: limit)
  195. .map(Index.init(first:))
  196. case (.first, .second):
  197. // impossible because `limit <= i`
  198. fatalError()
  199. case let (.second(i), .first(limit)):
  200. if let j = base2.index(i, offsetBy: -distance, limitedBy: base2.startIndex) {
  201. // the offset stays within the bounds of `base2`
  202. return Index(second: j)
  203. } else {
  204. // the offset overflows the bounds of `base2` by `n - d`
  205. let d = base2.distance(from: base2.startIndex, to: i)
  206. return base1.index(base1.endIndex, offsetBy: -(distance - d), limitedBy: limit)
  207. .map(Index.init(first:))
  208. }
  209. case let (.second(i), .second(limit)):
  210. // `limit` is relevant, so `base1` cannot be reached
  211. return base2.index(i, offsetBy: -distance, limitedBy: limit)
  212. .map(Index.init(second:))
  213. }
  214. }
  215. @inlinable
  216. public func distance(from start: Index, to end: Index) -> Int {
  217. switch (start.position, end.position) {
  218. case let (.first(i), .first(j)):
  219. return base1.distance(from: i, to: j)
  220. case let (.second(i), .second(j)):
  221. return base2.distance(from: i, to: j)
  222. case let (.first(i), .second(j)):
  223. return base1.distance(from: i, to: base1.endIndex)
  224. + base2.distance(from: base2.startIndex, to: j)
  225. case let (.second(i), .first(j)):
  226. return base2.distance(from: i, to: base2.startIndex)
  227. + base1.distance(from: base1.endIndex, to: j)
  228. }
  229. }
  230. }
  231. extension Chain2Sequence: BidirectionalCollection
  232. where Base1: BidirectionalCollection, Base2: BidirectionalCollection
  233. {
  234. @inlinable
  235. public func index(before i: Index) -> Index {
  236. assert(i != startIndex, "Can't advance before startIndex")
  237. switch i.position {
  238. case let .first(i):
  239. return Index(first: base1.index(before: i))
  240. case let .second(i):
  241. return i == base2.startIndex
  242. ? Index(first: base1.index(before: base1.endIndex))
  243. : Index(second: base2.index(before: i))
  244. }
  245. }
  246. }
  247. extension Chain2Sequence: RandomAccessCollection
  248. where Base1: RandomAccessCollection, Base2: RandomAccessCollection {}
  249. //===----------------------------------------------------------------------===//
  250. // chain(_:_:)
  251. //===----------------------------------------------------------------------===//
  252. /// Returns a new sequence that iterates over the two given sequences, one
  253. /// followed by the other.
  254. ///
  255. /// You can pass any two sequences or collections that have the same element
  256. /// type as this sequence. This example chains a closed range of `Int` with an
  257. /// array of `Int`:
  258. ///
  259. /// let small = 1...3
  260. /// let big = [100, 200, 300]
  261. /// for num in chain(small, big) {
  262. /// print(num)
  263. /// }
  264. /// // 1
  265. /// // 2
  266. /// // 3
  267. /// // 100
  268. /// // 200
  269. /// // 300
  270. ///
  271. /// - Parameters:
  272. /// - s1: The first sequence.
  273. /// - s2: The second sequence.
  274. /// - Returns: A sequence that iterates first over the elements of `s1`, and
  275. /// then over the elements of `s2`.
  276. ///
  277. /// - Complexity: O(1)
  278. @inlinable
  279. public func chain<S1, S2>(_ s1: S1, _ s2: S2) -> Chain2Sequence<S1, S2> {
  280. Chain2Sequence(base1: s1, base2: s2)
  281. }