9
9
//
10
10
//===----------------------------------------------------------------------===//
11
11
12
+ //===----------------------------------------------------------------------===//
13
+ // nextPermutation()
14
+ //===----------------------------------------------------------------------===//
15
+
16
+ extension MutableCollection
17
+ where Self: BidirectionalCollection , Element: Comparable
18
+ {
19
+ /// Permutes this collection's elements through all the lexical orderings.
20
+ ///
21
+ /// Call `nextPermutation()` repeatedly starting with the collection in
22
+ /// sorted order. When the full cycle of all permutations has been completed,
23
+ /// the collection will be back in sorted order and this method will return
24
+ /// `false`.
25
+ ///
26
+ /// - Returns: A Boolean value indicating whether the collection still has
27
+ /// remaining permutations. When this method returns `false`, the collection
28
+ /// is in ascending order according to `areInIncreasingOrder`.
29
+ ///
30
+ /// - Complexity: O(*n*), where *n* is the length of the collection.
31
+ @inlinable
32
+ internal mutating func nextPermutation( ) -> Bool {
33
+ // Ensure we have > 1 element in the collection.
34
+ guard !isEmpty else { return false }
35
+ var i = index ( before: endIndex)
36
+ if i == startIndex { return false }
37
+
38
+ while true {
39
+ let ip1 = i
40
+ formIndex ( before: & i)
41
+
42
+ if self [ i] < self [ ip1] {
43
+ var j = index ( before: endIndex)
44
+ while self [ i] >= self [ j] {
45
+ formIndex ( before: & j)
46
+ }
47
+ swapAt ( i, j)
48
+ self . reverse ( subrange: ip1 ..< endIndex)
49
+
50
+ // check here if i < the prefix, if so, return true, if not, continue
51
+ return true
52
+ }
53
+
54
+ if i == startIndex {
55
+ self . reverse ( )
56
+ return false
57
+ }
58
+ }
59
+ }
60
+
61
+ @inlinable
62
+ internal mutating func nextPermutation( upperBound: Index ) -> Bool {
63
+ // Ensure we have > 1 element in the collection.
64
+ guard !isEmpty else { return false }
65
+ var i = index ( before: endIndex)
66
+ if i == startIndex { return false }
67
+
68
+ while true {
69
+ let ip1 = i
70
+ formIndex ( before: & i)
71
+
72
+ // Find the last ascending pair (ie. ..., a, b, ... where a < b)
73
+ if self [ i] < self [ ip1] {
74
+ // Find the last element greater than self[i]
75
+ // This is _always_ at most `ip1` due to if statement above
76
+ let j = lastIndex ( where: { $0 > self [ i] } ) !
77
+
78
+ // At this point we have something like this:
79
+ // 0, 1, 4, 3, 2
80
+ // ^ ^
81
+ // i j
82
+ swapAt ( i, j)
83
+ self . reverse ( subrange: ip1 ..< endIndex)
84
+
85
+ // Only return if we've made a change within ..<upperBound region
86
+ if i < upperBound {
87
+ return true
88
+ } else {
89
+ i = index ( before: endIndex)
90
+ continue
91
+ }
92
+ }
93
+
94
+ if i == startIndex {
95
+ self . reverse ( )
96
+ return false
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ //===----------------------------------------------------------------------===//
103
+ // struct Permutations<Base>
104
+ //===----------------------------------------------------------------------===//
105
+
12
106
/// A sequence of all the permutations of a collection's elements.
13
107
public struct Permutations < Base: Collection > {
14
108
/// The base collection to iterate over for permutations.
@@ -194,54 +288,6 @@ extension Permutations: Sequence {
194
288
195
289
extension Permutations : LazySequenceProtocol where Base: LazySequenceProtocol { }
196
290
197
- //===----------------------------------------------------------------------===//
198
- // nextPermutation()
199
- //===----------------------------------------------------------------------===//
200
-
201
- extension MutableCollection
202
- where Self: BidirectionalCollection , Element: Comparable
203
- {
204
- /// Permutes this collection's elements through all the lexical orderings.
205
- ///
206
- /// Call `nextPermutation()` repeatedly starting with the collection in
207
- /// sorted order. When the full cycle of all permutations has been completed,
208
- /// the collection will be back in sorted order and this method will return
209
- /// `false`.
210
- ///
211
- /// - Returns: A Boolean value indicating whether the collection still has
212
- /// remaining permutations. When this method returns `false`, the collection
213
- /// is in ascending order according to `areInIncreasingOrder`.
214
- ///
215
- /// - Complexity: O(*n*), where *n* is the length of the collection.
216
- @usableFromInline
217
- internal mutating func nextPermutation( ) -> Bool {
218
- // Ensure we have > 1 element in the collection.
219
- guard !isEmpty else { return false }
220
- var i = index ( before: endIndex)
221
- if i == startIndex { return false }
222
-
223
- while true {
224
- let ip1 = i
225
- formIndex ( before: & i)
226
-
227
- if self [ i] < self [ ip1] {
228
- var j = index ( before: endIndex)
229
- while self [ i] >= self [ j] {
230
- formIndex ( before: & j)
231
- }
232
- swapAt ( i, j)
233
- self . reverse ( subrange: ip1 ..< endIndex)
234
- return true
235
- }
236
-
237
- if i == startIndex {
238
- self . reverse ( )
239
- return false
240
- }
241
- }
242
- }
243
- }
244
-
245
291
//===----------------------------------------------------------------------===//
246
292
// permutations(ofCount:)
247
293
//===----------------------------------------------------------------------===//
@@ -366,11 +412,25 @@ extension Collection {
366
412
367
413
public struct UniquePermutations < Element: Comparable > {
368
414
@usableFromInline
369
- let elements : [ Element ]
415
+ internal let elements : [ Element ]
370
416
417
+ @usableFromInline
418
+ internal let kRange : Range < Int >
419
+
420
+ @inlinable
421
+ internal init < S: Sequence > ( _ elements: S ) where S. Element == Element {
422
+ self . init ( elements, 0 ..< Int . max)
423
+ }
424
+
371
425
@inlinable
372
- init < S: Sequence > ( _ elements: S ) where S. Element == Element {
426
+ internal init < S: Sequence , R: RangeExpression > ( _ elements: S , _ range: R )
427
+ where S. Element == Element , R. Bound == Int
428
+ {
373
429
self . elements = elements. sorted ( )
430
+
431
+ let upperBound = self . elements. count + 1
432
+ self . kRange = range. relative ( to: 0 ..< . max)
433
+ . clamped ( to: 0 ..< upperBound)
374
434
}
375
435
}
376
436
@@ -380,27 +440,51 @@ extension UniquePermutations: Sequence {
380
440
var elements : [ Element ]
381
441
382
442
@usableFromInline
383
- var finished = false
443
+ enum State {
444
+ case start, middle, end
445
+ }
446
+
447
+ @usableFromInline
448
+ var state = State . start
449
+
450
+ @usableFromInline
451
+ var lengths : Range < Int >
384
452
385
453
@inlinable
386
- init ( _ elements: [ Element ] ) {
454
+ init ( _ elements: [ Element ] , lengths : Range < Int > ) {
387
455
self . elements = elements
456
+ self . lengths = lengths
388
457
}
389
458
390
459
@inlinable
391
- public mutating func next( ) -> [ Element ] ? {
392
- if finished {
460
+ public mutating func next( ) -> ArraySlice < Element > ? {
461
+ switch state {
462
+ case . start:
463
+ state = . middle
464
+ return elements [ ..< lengths. lowerBound]
465
+ case . middle:
466
+ if !elements. nextPermutation ( upperBound: lengths. lowerBound) {
467
+ lengths = ( lengths. lowerBound + 1 ) ..< lengths. upperBound
468
+
469
+ if lengths. isEmpty {
470
+ state = . end
471
+ return nil
472
+ }
473
+
474
+ elements. sort ( )
475
+ state = . start
476
+ }
477
+ return elements [ ..< lengths. lowerBound]
478
+
479
+ case . end:
393
480
return nil
394
- } else {
395
- defer { finished = !elements. nextPermutation ( ) }
396
- return elements
397
481
}
398
482
}
399
483
}
400
484
401
485
@inlinable
402
486
public func makeIterator( ) -> Iterator {
403
- Iterator ( elements)
487
+ Iterator ( elements, lengths : kRange )
404
488
}
405
489
}
406
490
@@ -437,4 +521,14 @@ extension Sequence where Element: Comparable {
437
521
public func uniquePermutations( ) -> UniquePermutations < Element > {
438
522
UniquePermutations ( self )
439
523
}
524
+
525
+ public func uniquePermutations( ofCount k: Int ) -> UniquePermutations < Element > {
526
+ UniquePermutations ( self , k ..< ( k + 1 ) )
527
+ }
528
+
529
+ public func uniquePermutations< R: RangeExpression > ( ofCount kRange: R ) -> UniquePermutations < Element >
530
+ where R. Bound == Int
531
+ {
532
+ UniquePermutations ( self , kRange)
533
+ }
440
534
}
0 commit comments