11
11
12
12
/// A sequence of all the permutations of a collection's elements.
13
13
public struct Permutations < Base: Collection > {
14
- /// The base collection.
14
+ /// The base collection to iterate over for permutations .
15
15
public let base : Base
16
16
17
+ @usableFromInline
17
18
internal let baseCount : Int
18
- internal let countToChoose : Int
19
19
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
20
32
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 {
21
52
self . base = base
22
53
let baseCount = base. count
23
54
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
25
59
}
26
60
61
+ /// The total number of permutations.
62
+ @inlinable
27
63
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 , + )
31
67
}
32
68
}
33
-
69
+
34
70
extension Permutations : Sequence {
35
71
/// The iterator for a `Permutations` instance.
36
72
public struct Iterator : IteratorProtocol {
37
73
@usableFromInline
38
74
internal var base : Base
75
+
39
76
@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.
43
83
@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)
47
87
@usableFromInline
48
- internal var permutesFullCollection : Bool {
49
- countToChoose == indexes . count
88
+ internal var isFinished : Bool {
89
+ return kRange . isEmpty
50
90
}
51
91
52
92
@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 ]
59
94
60
95
@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)
70
101
}
71
102
72
103
/// Advances the `indexes` array such that the first `countToChoose`
@@ -82,72 +113,92 @@ extension Permutations: Sequence {
82
113
/// - Complexity: O(*n*), where *n* is the length of the collection.
83
114
@usableFromInline
84
115
internal mutating func nextState( ) -> Bool {
116
+ let countToChoose = self . kRange. lowerBound
85
117
let edge = countToChoose - 1
86
-
118
+
87
119
// Find first index greater than the one at `edge`.
88
120
if let i = indexes [ countToChoose... ] . firstIndex ( where: { indexes [ edge] < $0 } ) {
89
121
indexes. swapAt ( edge, i)
90
122
} else {
91
- indexes. reverse ( subrange: countToChoose..< indexes. endIndex)
92
-
123
+ indexes. reverse ( subrange: countToChoose ..< indexes. endIndex)
124
+
93
125
// Find last increasing pair below `edge`.
94
126
// TODO: This could be indexes[..<edge].adjacentPairs().lastIndex(where: ...)
95
127
var lastAscent = edge - 1
96
128
while ( lastAscent >= 0 && indexes [ lastAscent] >= indexes [ lastAscent + 1 ] ) {
97
129
lastAscent -= 1
98
130
}
99
- if ( lastAscent < 0 ) {
131
+ if lastAscent < 0 {
100
132
return false
101
133
}
102
-
134
+
103
135
// Find rightmost index less than that at `lastAscent`.
104
136
if let i = indexes [ lastAscent... ] . lastIndex ( where: { indexes [ lastAscent] < $0 } ) {
105
137
indexes. swapAt ( lastAscent, i)
106
138
}
107
- indexes. reverse ( subrange: ( lastAscent + 1 ) ..< indexes. endIndex)
139
+ indexes. reverse ( subrange: ( lastAscent + 1 ) ..< indexes. endIndex)
108
140
}
109
141
110
142
return true
111
143
}
112
144
113
145
@inlinable
114
146
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
+ }
116
163
164
+ let permutesFullCollection = ( countToChoose == baseCount)
117
165
if permutesFullCollection {
118
166
// If we're permuting the full collection, each iteration is just a
119
167
// call to `nextPermutation` on `indexes`.
120
- defer { hasMorePermutations = indexes. nextPermutation ( ) }
168
+ defer {
169
+ let hasMorePermutations = indexes. nextPermutation ( )
170
+ if !hasMorePermutations {
171
+ advanceKRange ( )
172
+ }
173
+ }
121
174
return indexes. map { base [ $0] }
122
175
} else {
123
176
// Otherwise, return the items at the first `countToChoose` indices and
124
177
// advance the state.
125
- defer { hasMorePermutations = nextState ( ) }
178
+ defer {
179
+ let hasMorePermutations = nextState ( )
180
+ if !hasMorePermutations {
181
+ advanceKRange ( )
182
+ }
183
+ }
126
184
return indexes. prefix ( countToChoose) . map { base [ $0] }
127
185
}
128
186
}
129
187
}
130
188
131
- @usableFromInline
132
- internal var permutesFullCollection : Bool {
133
- baseCount == countToChoose
134
- }
135
-
136
189
public func makeIterator( ) -> Iterator {
137
- permutesFullCollection
138
- ? Iterator ( base)
139
- : Iterator ( base, count: countToChoose)
190
+ Iterator ( self )
140
191
}
141
192
}
142
193
143
194
extension Permutations : LazySequenceProtocol where Base: LazySequenceProtocol { }
144
195
145
196
//===----------------------------------------------------------------------===//
146
- // nextPermutation(by: )
197
+ // nextPermutation()
147
198
//===----------------------------------------------------------------------===//
148
199
149
200
extension MutableCollection
150
- where Self: BidirectionalCollection , Element: Comparable
201
+ where Self: BidirectionalCollection , Element: Comparable
151
202
{
152
203
/// Permutes this collection's elements through all the lexical orderings.
153
204
///
@@ -163,8 +214,8 @@ extension MutableCollection
163
214
/// - Complexity: O(*n*), where *n* is the length of the collection.
164
215
@usableFromInline
165
216
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 }
168
219
var i = index ( before: endIndex)
169
220
if i == startIndex { return false }
170
221
@@ -178,7 +229,7 @@ extension MutableCollection
178
229
formIndex ( before: & j)
179
230
}
180
231
swapAt ( i, j)
181
- self . reverse ( subrange: ip1..< endIndex)
232
+ self . reverse ( subrange: ip1 ..< endIndex)
182
233
return true
183
234
}
184
235
@@ -195,6 +246,62 @@ extension MutableCollection
195
246
//===----------------------------------------------------------------------===//
196
247
197
248
extension 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
+
198
305
/// Returns a collection of the permutations of this collection of the
199
306
/// specified length.
200
307
///
@@ -237,10 +344,13 @@ extension Collection {
237
344
/// sequence, the resulting sequence has no elements.
238
345
///
239
346
/// - 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.
242
349
///
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
244
354
public func permutations( ofCount k: Int ? = nil ) -> Permutations < Self > {
245
355
precondition (
246
356
k ?? 0 >= 0 ,
0 commit comments