@@ -29,7 +29,7 @@ extension MutableCollection
29
29
///
30
30
/// - Complexity: O(*n*), where *n* is the length of the collection.
31
31
@inlinable
32
- internal mutating func nextPermutation ( ) -> Bool {
32
+ internal mutating func nextPermutation2 ( ) -> Bool {
33
33
// Ensure we have > 1 element in the collection.
34
34
guard !isEmpty else { return false }
35
35
var i = index ( before: endIndex)
@@ -57,25 +57,25 @@ extension MutableCollection
57
57
}
58
58
}
59
59
}
60
- }
61
60
62
- extension MutableCollection where Self: BidirectionalCollection {
63
61
@inlinable
64
- internal mutating func nextPermutation( upperBound: Index , by areInIncreasingOrder : ( Element , Element ) -> Bool ) -> Bool {
62
+ internal mutating func nextPermutation( upperBound: Index ? = nil ) -> Bool {
65
63
// Ensure we have > 1 element in the collection.
66
64
guard !isEmpty else { return false }
67
65
var i = index ( before: endIndex)
68
66
if i == startIndex { return false }
69
67
68
+ let upperBound = upperBound ?? endIndex
69
+
70
70
while true {
71
71
let ip1 = i
72
72
formIndex ( before: & i)
73
73
74
74
// Find the last ascending pair (ie. ..., a, b, ... where a < b)
75
- if areInIncreasingOrder ( self [ i] , self [ ip1] ) {
75
+ if self [ i] < self [ ip1] {
76
76
// Find the last element greater than self[i]
77
77
// This is _always_ at most `ip1` due to if statement above
78
- let j = lastIndex ( where: { areInIncreasingOrder ( self [ i] , $0 ) } ) !
78
+ let j = lastIndex ( where: { self [ i] < $0 } ) !
79
79
80
80
// At this point we have something like this:
81
81
// 0, 1, 4, 3, 2
@@ -420,27 +420,35 @@ extension Collection {
420
420
///
421
421
/// To create a `UniquePermutations` instance, call one of the
422
422
/// `uniquePermutations` methods on your collection.
423
- public struct UniquePermutations < Element> {
423
+ public struct UniquePermutations < Base: Collection > where Base. Element: Hashable {
424
+ @usableFromInline
425
+ internal let elements : Base
426
+
424
427
@usableFromInline
425
- internal let elements : [ Element ]
428
+ internal var indexes : [ Base . Index ]
426
429
427
430
@usableFromInline
428
431
internal let kRange : Range < Int >
429
432
430
- @usableFromInline
431
- internal let areInIncreasingOrder : ( Element , Element ) -> Bool
432
-
433
433
@inlinable
434
- internal init < S : Sequence > ( _ elements: S , by areInIncreasingOrder : @escaping ( Element , Element ) -> Bool ) where S . Element == Element {
435
- self . init ( elements, 0 ..< Int . max, by : areInIncreasingOrder )
434
+ internal init ( _ elements: Base ) {
435
+ self . init ( elements, 0 ..< Int . max)
436
436
}
437
437
438
438
@inlinable
439
- internal init < S : Sequence , R: RangeExpression > ( _ elements: S , _ range: R , by areInIncreasingOrder : @escaping ( Element , Element ) -> Bool )
440
- where S . Element == Element , R. Bound == Int
439
+ internal init < R: RangeExpression > ( _ elements: Base , _ range: R )
440
+ where R. Bound == Int
441
441
{
442
- self . elements = elements. sorted ( by: areInIncreasingOrder)
443
- self . areInIncreasingOrder = areInIncreasingOrder
442
+ let firstIndexesAndCountsByElement = Dictionary (
443
+ elements. indices. lazy. map { ( elements [ $0] , ( $0, 1 ) ) } ,
444
+ uniquingKeysWith: { indexAndCount, _ in ( indexAndCount. 0 , indexAndCount. 1 + 1 ) } )
445
+
446
+ self . indexes = Array ( firstIndexesAndCountsByElement
447
+ . values. sorted ( by: { $0. 0 < $1. 0 } )
448
+ . map { index, count in repeatElement ( index, count: count) }
449
+ . joined ( ) )
450
+
451
+ self . elements = elements
444
452
445
453
let upperBound = self . elements. count + 1
446
454
self . kRange = range. relative ( to: 0 ..< . max)
@@ -449,29 +457,31 @@ public struct UniquePermutations<Element> {
449
457
}
450
458
451
459
extension UniquePermutations : Sequence {
460
+ public typealias Element = [ Base . Element ]
461
+
452
462
/// The iterator for a `UniquePermutations` instance.
453
463
public struct Iterator : IteratorProtocol {
454
464
@usableFromInline
455
- var elements : [ Element ]
456
-
457
- @usableFromInline
458
- var initial = true
465
+ internal let elements : Base
459
466
460
467
@usableFromInline
461
- var lengths : Range < Int >
468
+ internal var indexes : [ Base . Index ]
462
469
463
470
@usableFromInline
464
- internal let areInIncreasingOrder : ( Element , Element ) -> Bool
465
-
471
+ internal var lengths : Range < Int >
472
+
473
+ @usableFromInline
474
+ internal var initial = true
475
+
466
476
@inlinable
467
- init ( _ elements: [ Element ] , lengths: Range < Int > , by areInIncreasingOrder : @escaping ( Element , Element ) -> Bool ) {
477
+ internal init ( _ elements: Base , indexes : [ Base . Index ] , lengths: Range < Int > ) {
468
478
self . elements = elements
479
+ self . indexes = indexes
469
480
self . lengths = lengths
470
- self . areInIncreasingOrder = areInIncreasingOrder
471
481
}
472
482
473
483
@inlinable
474
- public mutating func next( ) -> ArraySlice < Element > ? {
484
+ public mutating func next( ) -> [ Base . Element ] ? {
475
485
// In the end case, `lengths` is an empty range.
476
486
if lengths. isEmpty {
477
487
return nil
@@ -483,28 +493,28 @@ extension UniquePermutations: Sequence {
483
493
// copying when possible.
484
494
if initial {
485
495
initial = false
486
- return elements [ ..< lengths. lowerBound]
496
+ return indexes [ ..< lengths. lowerBound] . map { elements [ $0 ] }
487
497
}
488
498
489
- if !elements . nextPermutation ( upperBound: lengths. lowerBound, by : areInIncreasingOrder ) {
499
+ if !indexes . nextPermutation ( upperBound: lengths. lowerBound) {
490
500
lengths = ( lengths. lowerBound + 1 ) ..< lengths. upperBound
491
501
492
502
if lengths. isEmpty {
493
503
return nil
494
504
}
495
505
}
496
506
497
- return elements [ ..< lengths. lowerBound]
507
+ return indexes [ ..< lengths. lowerBound] . map { elements [ $0 ] }
498
508
}
499
509
}
500
510
501
511
@inlinable
502
512
public func makeIterator( ) -> Iterator {
503
- Iterator ( elements, lengths : kRange , by : areInIncreasingOrder )
513
+ Iterator ( elements, indexes : indexes , lengths : kRange )
504
514
}
505
515
}
506
516
507
- extension Sequence where Element: Comparable {
517
+ extension Collection where Element: Hashable {
508
518
/// Returns a sequence of the unique permutations of this sequence.
509
519
///
510
520
/// Use this method to iterate over the unique permutations of a sequence
@@ -534,8 +544,8 @@ extension Sequence where Element: Comparable {
534
544
/// // [2, 2, 1]
535
545
///
536
546
/// The returned permutations are in lexicographically sorted order.
537
- public func uniquePermutations( ) -> UniquePermutations < Element > {
538
- UniquePermutations ( self , by : < )
547
+ public func uniquePermutations( ) -> UniquePermutations < Self > {
548
+ UniquePermutations ( self )
539
549
}
540
550
541
551
/// Returns a sequence of the unique permutations of this sequence of the
@@ -568,8 +578,8 @@ extension Sequence where Element: Comparable {
568
578
/// // [2, 1]
569
579
///
570
580
/// The returned permutations are in lexicographically sorted order.
571
- public func uniquePermutations( ofCount k: Int ) -> UniquePermutations < Element > {
572
- UniquePermutations ( self , k ..< ( k + 1 ) , by : < )
581
+ public func uniquePermutations( ofCount k: Int ) -> UniquePermutations < Self > {
582
+ UniquePermutations ( self , k ..< ( k + 1 ) )
573
583
}
574
584
575
585
/// Returns a collection of the unique permutations of this sequence with
@@ -592,39 +602,9 @@ extension Sequence where Element: Comparable {
592
602
///
593
603
/// The returned permutations are in ascending order by length, and then
594
604
/// lexicographically within each group of the same length.
595
- public func uniquePermutations< R: RangeExpression > ( ofCount kRange: R ) -> UniquePermutations < Element >
596
- where R. Bound == Int
597
- {
598
- UniquePermutations ( self , kRange, by: < )
599
- }
600
- }
601
-
602
- extension Sequence {
603
- /// Returns a sequence of the unique permutations of this sequence.
604
- public func uniquePermutations(
605
- by areInIncreasingOrder: @escaping ( Element , Element ) -> Bool
606
- ) -> UniquePermutations < Element > {
607
- UniquePermutations ( self , by: areInIncreasingOrder)
608
- }
609
-
610
- /// Returns a sequence of the unique permutations of this sequence of the
611
- /// specified length.
612
- ///
613
- public func uniquePermutations(
614
- ofCount k: Int ,
615
- by areInIncreasingOrder: @escaping ( Element , Element ) -> Bool
616
- ) -> UniquePermutations < Element > {
617
- UniquePermutations ( self , k ..< ( k + 1 ) , by: areInIncreasingOrder)
618
- }
619
-
620
- /// Returns a collection of the unique permutations of this sequence with
621
- /// lengths in the specified range.
622
- public func uniquePermutations< R: RangeExpression > (
623
- ofCount kRange: R ,
624
- by areInIncreasingOrder: @escaping ( Element , Element ) -> Bool
625
- ) -> UniquePermutations < Element >
605
+ public func uniquePermutations< R: RangeExpression > ( ofCount kRange: R ) -> UniquePermutations < Self >
626
606
where R. Bound == Int
627
607
{
628
- UniquePermutations ( self , kRange, by : areInIncreasingOrder )
608
+ UniquePermutations ( self , kRange)
629
609
}
630
610
}
0 commit comments