1111
1212/// A sequence of all the permutations of a collection's elements.
1313public struct Permutations < Base: Collection > {
14- /// The base collection.
14+ /// The base collection to iterate over for permutations .
1515 public let base : Base
1616
17+ @usableFromInline
1718 internal let baseCount : Int
18- internal let countToChoose : Int
1919
20+ /// The range of accepted sizes of permutations.
21+ /// - Note: This may be empty if the attempted range entirely exceeds the
22+ /// bounds of the size of the `base` collection.
23+ @usableFromInline
24+ internal let kRange : Range < Int >
25+
26+ /// Initializes a `Permutations` for all permutations of `base` of size `k`.
27+ /// - Parameters:
28+ /// - base: The collection to iterate over for permutations
29+ /// - k: The expected size of each permutation, or `nil` (default) to
30+ /// iterate over all permutations of the same size as the base collection.
31+ @usableFromInline
2032 internal init ( _ base: Base , k: Int ? = nil ) {
33+ let kRange : ClosedRange < Int > ?
34+ if let countToChoose = k {
35+ kRange = countToChoose ... countToChoose
36+ } else {
37+ kRange = nil
38+ }
39+ self . init ( base, kRange: kRange)
40+ }
41+
42+ /// Initializes a `Permutations` for all combinations of `base` of sizes
43+ /// within a given range.
44+ /// - Parameters:
45+ /// - base: The collection to iterate over for permutations.
46+ /// - kRange: The range of accepted sizes of permutations, or `nil` to
47+ /// iterate over all permutations of the same size as the base collection.
48+ @usableFromInline
49+ internal init < R: RangeExpression > (
50+ _ base: Base , kRange: R ?
51+ ) where R. Bound == Int {
2152 self . base = base
2253 let baseCount = base. count
2354 self . baseCount = baseCount
24- self . countToChoose = k ?? baseCount
55+ let upperBound = baseCount + 1
56+ self . kRange = kRange? . relative ( to: 0 ..< . max)
57+ . clamped ( to: 0 ..< upperBound) ??
58+ baseCount ..< upperBound
2559 }
2660
61+ /// The total number of permutations.
62+ @inlinable
2763 public var count : Int {
28- return baseCount >= countToChoose
29- ? stride ( from: baseCount, to: baseCount - countToChoose , by: - 1 ) . reduce ( 1 , * )
30- : 0
64+ return kRange . map {
65+ stride ( from: baseCount, to: baseCount - $0 , by: - 1 ) . reduce ( 1 , * )
66+ } . reduce ( 0 , + )
3167 }
3268}
33-
69+
3470extension Permutations : Sequence {
3571 /// The iterator for a `Permutations` instance.
3672 public struct Iterator : IteratorProtocol {
3773 @usableFromInline
3874 internal var base : Base
75+
3976 @usableFromInline
40- internal var indexes : [ Base . Index ]
41- @usableFromInline
42- internal var hasMorePermutations : Bool
77+ internal let baseCount : Int
78+
79+ /// The current range of accepted sizes of permutations.
80+ /// - Note: The range is contracted until empty while iterating over
81+ /// permutations of different sizes. When the range is empty, iteration is
82+ /// finished.
4383 @usableFromInline
44- internal var countToChoose : Int = 0
45-
46- /// `true` if we're generating permutations of the full collection.
84+ internal var kRange : Range < Int >
85+
86+ /// Whether or not iteration is finished (`kRange` is empty)
4787 @usableFromInline
48- internal var permutesFullCollection : Bool {
49- countToChoose == indexes . count
88+ internal var isFinished : Bool {
89+ return kRange . isEmpty
5090 }
5191
5292 @usableFromInline
53- internal init ( _ base: Base ) {
54- self . base = base
55- self . indexes = Array ( base. indices)
56- self . countToChoose = self . indexes. count
57- self . hasMorePermutations = true
58- }
93+ internal var indexes : [ Base . Index ]
5994
6095 @usableFromInline
61- internal init ( _ base: Base , count: Int ) {
62- self . base = base
63- self . countToChoose = count
64-
65- // Produce exactly one empty permutation when `count == 0`.
66- self . indexes = count == 0 ? [ ] : Array ( base. indices)
67-
68- // Can't produce any permutations when `count > base.count`.
69- self . hasMorePermutations = count <= indexes. count
96+ internal init ( _ permutations: Permutations ) {
97+ self . base = permutations. base
98+ self . baseCount = permutations. baseCount
99+ self . kRange = permutations. kRange
100+ self . indexes = Array ( permutations. base. indices)
70101 }
71102
72103 /// Advances the `indexes` array such that the first `countToChoose`
@@ -82,72 +113,92 @@ extension Permutations: Sequence {
82113 /// - Complexity: O(*n*), where *n* is the length of the collection.
83114 @usableFromInline
84115 internal mutating func nextState( ) -> Bool {
116+ let countToChoose = self . kRange. lowerBound
85117 let edge = countToChoose - 1
86-
118+
87119 // Find first index greater than the one at `edge`.
88120 if let i = indexes [ countToChoose... ] . firstIndex ( where: { indexes [ edge] < $0 } ) {
89121 indexes. swapAt ( edge, i)
90122 } else {
91- indexes. reverse ( subrange: countToChoose..< indexes. endIndex)
92-
123+ indexes. reverse ( subrange: countToChoose ..< indexes. endIndex)
124+
93125 // Find last increasing pair below `edge`.
94126 // TODO: This could be indexes[..<edge].adjacentPairs().lastIndex(where: ...)
95127 var lastAscent = edge - 1
96128 while ( lastAscent >= 0 && indexes [ lastAscent] >= indexes [ lastAscent + 1 ] ) {
97129 lastAscent -= 1
98130 }
99- if ( lastAscent < 0 ) {
131+ if lastAscent < 0 {
100132 return false
101133 }
102-
134+
103135 // Find rightmost index less than that at `lastAscent`.
104136 if let i = indexes [ lastAscent... ] . lastIndex ( where: { indexes [ lastAscent] < $0 } ) {
105137 indexes. swapAt ( lastAscent, i)
106138 }
107- indexes. reverse ( subrange: ( lastAscent + 1 ) ..< indexes. endIndex)
139+ indexes. reverse ( subrange: ( lastAscent + 1 ) ..< indexes. endIndex)
108140 }
109141
110142 return true
111143 }
112144
113145 @inlinable
114146 public mutating func next( ) -> [ Base . Element ] ? {
115- if !hasMorePermutations { return nil }
147+ guard !isFinished else { return nil }
148+
149+ /// Advances `kRange` by incrementing its `lowerBound` until the range is
150+ /// empty, when iteration is finished.
151+ func advanceKRange( ) {
152+ kRange. removeFirst ( )
153+ indexes = Array ( base. indices)
154+ }
155+
156+ let countToChoose = self . kRange. lowerBound
157+ if countToChoose == 0 {
158+ defer {
159+ advanceKRange ( )
160+ }
161+ return [ ]
162+ }
116163
164+ let permutesFullCollection = ( countToChoose == baseCount)
117165 if permutesFullCollection {
118166 // If we're permuting the full collection, each iteration is just a
119167 // call to `nextPermutation` on `indexes`.
120- defer { hasMorePermutations = indexes. nextPermutation ( ) }
168+ defer {
169+ let hasMorePermutations = indexes. nextPermutation ( )
170+ if !hasMorePermutations {
171+ advanceKRange ( )
172+ }
173+ }
121174 return indexes. map { base [ $0] }
122175 } else {
123176 // Otherwise, return the items at the first `countToChoose` indices and
124177 // advance the state.
125- defer { hasMorePermutations = nextState ( ) }
178+ defer {
179+ let hasMorePermutations = nextState ( )
180+ if !hasMorePermutations {
181+ advanceKRange ( )
182+ }
183+ }
126184 return indexes. prefix ( countToChoose) . map { base [ $0] }
127185 }
128186 }
129187 }
130188
131- @usableFromInline
132- internal var permutesFullCollection : Bool {
133- baseCount == countToChoose
134- }
135-
136189 public func makeIterator( ) -> Iterator {
137- permutesFullCollection
138- ? Iterator ( base)
139- : Iterator ( base, count: countToChoose)
190+ Iterator ( self )
140191 }
141192}
142193
143194extension Permutations : LazySequenceProtocol where Base: LazySequenceProtocol { }
144195
145196//===----------------------------------------------------------------------===//
146- // nextPermutation(by: )
197+ // nextPermutation()
147198//===----------------------------------------------------------------------===//
148199
149200extension MutableCollection
150- where Self: BidirectionalCollection , Element: Comparable
201+ where Self: BidirectionalCollection , Element: Comparable
151202{
152203 /// Permutes this collection's elements through all the lexical orderings.
153204 ///
@@ -163,8 +214,8 @@ extension MutableCollection
163214 /// - Complexity: O(*n*), where *n* is the length of the collection.
164215 @usableFromInline
165216 internal mutating func nextPermutation( ) -> Bool {
166- // ensure we have > 1 element in the collection
167- if isEmpty { return false }
217+ // Ensure we have > 1 element in the collection.
218+ guard ! isEmpty else { return false }
168219 var i = index ( before: endIndex)
169220 if i == startIndex { return false }
170221
@@ -178,7 +229,7 @@ extension MutableCollection
178229 formIndex ( before: & j)
179230 }
180231 swapAt ( i, j)
181- self . reverse ( subrange: ip1..< endIndex)
232+ self . reverse ( subrange: ip1 ..< endIndex)
182233 return true
183234 }
184235
@@ -195,6 +246,62 @@ extension MutableCollection
195246//===----------------------------------------------------------------------===//
196247
197248extension Collection {
249+ /// Returns a collection of the permutations of this collection with lengths
250+ /// in the specified range.
251+ ///
252+ /// This example prints the different permutations of one to two elements from
253+ /// an array of three names:
254+ ///
255+ /// let names = ["Alex", "Celeste", "Davide"]
256+ /// for perm in names.permutations(ofCount: 1...2) {
257+ /// print(perm.joined(separator: ", "))
258+ /// }
259+ /// // Alex
260+ /// // Celeste
261+ /// // Davide
262+ /// // Alex, Celeste
263+ /// // Alex, Davide
264+ /// // Celeste, Alex
265+ /// // Celeste, Davide
266+ /// // Davide, Alex
267+ /// // Davide, Celeste
268+ ///
269+ /// This example prints _all_ the permutations (including an empty array) from
270+ /// the an array of numbers:
271+ ///
272+ /// let numbers = [10, 20, 30]
273+ /// for perm in numbers.permutations(ofCount: 0...) {
274+ /// print(perm)
275+ /// }
276+ /// // []
277+ /// // [10]
278+ /// // [20]
279+ /// // [30]
280+ /// // [10, 20]
281+ /// // [10, 30]
282+ /// // [20, 10]
283+ /// // [20, 30]
284+ /// // [30, 10]
285+ /// // [30, 20]
286+ /// // [10, 20, 30]
287+ /// // [10, 30, 20]
288+ /// // [20, 10, 30]
289+ /// // [20, 30, 10]
290+ /// // [30, 10, 20]
291+ /// // [30, 20, 10]
292+ ///
293+ /// - Parameter kRange: The number of elements to include in each permutation.
294+ ///
295+ /// - Complexity: O(1) for random-access base collections. O(*n*) where *n*
296+ /// is the number of elements in the base collection, since `Permutations`
297+ /// accesses the `count` of the base collection.
298+ @inlinable
299+ public func permutations< R: RangeExpression > (
300+ ofCount kRange: R
301+ ) -> Permutations < Self > where R. Bound == Int {
302+ return Permutations ( self , kRange: kRange)
303+ }
304+
198305 /// Returns a collection of the permutations of this collection of the
199306 /// specified length.
200307 ///
@@ -237,10 +344,13 @@ extension Collection {
237344 /// sequence, the resulting sequence has no elements.
238345 ///
239346 /// - Parameter k: The number of elements to include in each permutation.
240- /// If `count ` is `nil`, the resulting sequence represents permutations
241- /// of this entire collection.
347+ /// If `k ` is `nil`, the resulting sequence represents permutations of this
348+ /// entire collection.
242349 ///
243- /// - Complexity: O(1)
350+ /// - Complexity: O(1) for random-access base collections. O(*n*) where *n*
351+ /// is the number of elements in the base collection, since `Permutations`
352+ /// accesses the `count` of the base collection.
353+ @inlinable
244354 public func permutations( ofCount k: Int ? = nil ) -> Permutations < Self > {
245355 precondition (
246356 k ?? 0 >= 0 ,
0 commit comments