@@ -18,8 +18,48 @@ import StdlibUnittest
18
18
//===--- Rotate -----------------------------------------------------------===//
19
19
//===----------------------------------------------------------------------===//
20
20
21
+ public protocol CollectionAlgorithms : Collection
22
+ where SubSequence : CollectionAlgorithms
23
+ {
24
+ func lastIndex( where predicate: ( Element ) throws -> Bool ) rethrows -> Index ?
25
+ func _indexAfterLastIndex(
26
+ where predicate: ( Element ) throws -> Bool
27
+ ) rethrows -> Index ?
28
+ }
29
+
30
+ extension Collection {
31
+ public func lastIndex(
32
+ where predicate: ( Element ) throws -> Bool
33
+ ) rethrows -> Index ? {
34
+ return try indices. reduce ( nil ) {
35
+ r, i in try predicate ( self [ i] ) ? i as Optional : r
36
+ }
37
+ }
38
+
39
+ public func _indexAfterLastIndex(
40
+ where predicate: ( Element ) throws -> Bool
41
+ ) rethrows -> Index ? {
42
+ return try lastIndex ( where: predicate) . map { index ( after: $0) }
43
+ }
44
+ }
45
+
46
+ extension BidirectionalCollection {
47
+ public func lastIndex(
48
+ where predicate: ( Element ) throws -> Bool
49
+ ) rethrows -> Index ? {
50
+ return try indices. reversed ( ) . first { try predicate ( self [ $0] ) }
51
+ }
52
+
53
+ public func _indexAfterLastIndex(
54
+ where predicate: ( Element ) throws -> Bool
55
+ ) rethrows -> Index ? {
56
+ return try self . reversed ( ) . firstIndex ( where: predicate) ? . base
57
+ }
58
+ }
59
+
21
60
// In the stdlib, this would simply be MutableCollection
22
- public protocol MutableCollectionAlgorithms : MutableCollection
61
+ public protocol MutableCollectionAlgorithms
62
+ : MutableCollection , CollectionAlgorithms
23
63
where SubSequence : MutableCollectionAlgorithms
24
64
{
25
65
/// Rotates the elements of the collection so that the element
@@ -36,7 +76,8 @@ public protocol MutableCollectionAlgorithms : MutableCollection
36
76
extension Array : MutableCollectionAlgorithms { }
37
77
extension ArraySlice : MutableCollectionAlgorithms { }
38
78
39
- extension Slice : MutableCollectionAlgorithms where Base: MutableCollection { }
79
+ extension Slice : MutableCollectionAlgorithms , CollectionAlgorithms
80
+ where Base: MutableCollection { }
40
81
41
82
/// In the stdlib, this would simply be MutableCollection
42
83
extension MutableCollectionAlgorithms {
@@ -516,64 +557,55 @@ extension Collection {
516
557
//===--- Stable Partition -------------------------------------------------===//
517
558
//===----------------------------------------------------------------------===//
518
559
519
- extension BidirectionalCollection
520
- where Self : MutableCollectionAlgorithms {
560
+ extension Collection
561
+ where Self : MutableCollectionAlgorithms {
521
562
522
563
@discardableResult
523
564
mutating func stablePartition(
524
- choosingStartGroupBy p: ( Element ) -> Bool
525
- ) -> Index {
526
- return _stablePartition (
527
- distance: distance ( from: startIndex, to: endIndex) ,
528
- choosingStartGroupBy: p
529
- )
530
- }
531
-
532
- mutating func _stablePartition(
533
- distance n: Int ,
534
- choosingStartGroupBy p: ( Element ) -> Bool
535
- ) -> Index {
536
- assert ( n >= 0 )
537
- assert ( n == distance ( from: startIndex, to: endIndex) )
538
- if n == 0 { return startIndex }
539
- if n == 1 {
540
- return p ( self [ startIndex] ) ? endIndex : startIndex
565
+ isSuffixElement: ( Element ) throws -> Bool
566
+ ) rethrows -> Index {
567
+ return try stablePartition (
568
+ count: count, isSuffixElement: isSuffixElement)
569
+ }
570
+
571
+ /// Moves all elements satisfying `isSuffixElement` into a suffix of the collection,
572
+ /// preserving their relative order, returning the start of the resulting suffix.
573
+ ///
574
+ /// - Complexity: O(n) where n is the number of elements.
575
+ /// - Precondition: `n == self.count`
576
+ fileprivate mutating func stablePartition(
577
+ count n: Int , isSuffixElement: ( Element ) throws -> Bool
578
+ ) rethrows -> Index {
579
+ if n == 0 { return startIndex }
580
+ if n == 1 {
581
+ return try isSuffixElement ( self [ startIndex] ) ? startIndex : endIndex
582
+ }
583
+ let h = n / 2 , i = index ( startIndex, offsetBy: h)
584
+ let j = try self [ ..< i] . stablePartition (
585
+ count: h, isSuffixElement: isSuffixElement)
586
+ let k = try self [ i... ] . stablePartition (
587
+ count: n - h, isSuffixElement: isSuffixElement)
588
+ return self [ j..< k] . rotate ( shiftingToStart: i)
541
589
}
542
-
543
- // divide and conquer.
544
- let d = n / numericCast( 2 )
545
- let m = index ( startIndex, offsetBy: d)
546
-
547
- // TTTTTTTTT s FFFFFFF m ?????????????
548
- let s = self [ ..< m] . _stablePartition (
549
- distance: numericCast ( d) , choosingStartGroupBy: p)
550
-
551
- // TTTTTTTTT s FFFFFFF m TTTTTTT e FFFFFFFF
552
- let e = self [ m... ] . _stablePartition (
553
- distance: numericCast ( n - d) , choosingStartGroupBy: p)
554
-
555
- // TTTTTTTTT s TTTTTTT m FFFFFFF e FFFFFFFF
556
- return self [ s..< e] . rotate ( shiftingToStart: m)
557
- }
558
590
}
559
591
560
592
extension Collection {
561
- func stablyPartitioned(
562
- choosingStartGroupBy p: ( Element ) -> Bool
563
- ) -> [ Element ] {
564
- var a = Array ( self )
565
- a. stablePartition ( choosingStartGroupBy : p)
566
- return a
567
- }
593
+ func stablyPartitioned(
594
+ isSuffixElement p: ( Element ) -> Bool
595
+ ) -> [ Element ] {
596
+ var a = Array ( self )
597
+ a. stablePartition ( isSuffixElement : p)
598
+ return a
599
+ }
568
600
}
569
601
570
602
extension LazyCollectionProtocol
571
- where Element == Elements . Element {
572
- func stablyPartitioned(
573
- choosingStartGroupBy p: ( Element ) -> Bool
574
- ) -> LazyCollection < [ Element ] > {
575
- return elements. stablyPartitioned ( choosingStartGroupBy : p) . lazy
576
- }
603
+ where Element == Elements . Element {
604
+ func stablyPartitioned(
605
+ isSuffixElement p: ( Element ) -> Bool
606
+ ) -> LazyCollection < [ Element ] > {
607
+ return elements. stablyPartitioned ( isSuffixElement : p) . lazy
608
+ }
577
609
}
578
610
579
611
extension Collection {
@@ -722,41 +754,41 @@ suite.test("stablePartition") {
722
754
let subrange = a [ p..< q]
723
755
724
756
for modulus in 1 ... 5 {
725
- let f = { $0 % modulus = = 0 }
757
+ let f = { $0 % modulus ! = 0 }
726
758
let notf = { !f( $0) }
727
759
728
760
var b = a
729
761
b. reserveCapacity ( b. count) // guarantee unique storage
730
762
let id = address ( b)
731
763
732
- var r = b [ p..< q] . stablePartition ( choosingStartGroupBy : f)
764
+ var r = b [ p..< q] . stablePartition ( isSuffixElement : f)
733
765
expectEqual ( b [ ..< p] , prefix)
734
766
expectEqual ( b. suffix ( from: q) , suffix)
735
- expectEqual ( b [ p..< r] , ArraySlice ( subrange. filter ( f ) ) )
736
- expectEqual ( b [ r..< q] , ArraySlice ( subrange. filter ( notf ) ) )
767
+ expectEqual ( b [ p..< r] , ArraySlice ( subrange. filter ( notf ) ) )
768
+ expectEqual ( b [ r..< q] , ArraySlice ( subrange. filter ( f ) ) )
737
769
expectEqual ( address ( b) , id)
738
770
739
771
b = a
740
- r = b [ p..< q] . stablePartition ( choosingStartGroupBy : notf)
772
+ r = b [ p..< q] . stablePartition ( isSuffixElement : notf)
741
773
expectEqual ( b [ ..< p] , prefix)
742
774
expectEqual ( b. suffix ( from: q) , suffix)
743
- expectEqual ( b [ p..< r] , ArraySlice ( subrange. filter ( notf ) ) )
744
- expectEqual ( b [ r..< q] , ArraySlice ( subrange. filter ( f ) ) )
775
+ expectEqual ( b [ p..< r] , ArraySlice ( subrange. filter ( f ) ) )
776
+ expectEqual ( b [ r..< q] , ArraySlice ( subrange. filter ( notf ) ) )
745
777
}
746
778
}
747
779
748
780
for modulus in 1 ... 5 {
749
- let f = { $0 % modulus = = 0 }
781
+ let f = { $0 % modulus ! = 0 }
750
782
let notf = { !f( $0) }
751
783
var b = a
752
- var r = b. stablePartition ( choosingStartGroupBy: f)
753
- expectEqual ( b [ ..< r] , ArraySlice ( a. filter ( f) ) )
754
- expectEqual ( b [ r... ] , ArraySlice ( a. filter ( notf) ) )
755
-
756
- b = a
757
- r = b. stablePartition ( choosingStartGroupBy: notf)
784
+ var r = b. stablePartition ( isSuffixElement: f)
758
785
expectEqual ( b [ ..< r] , ArraySlice ( a. filter ( notf) ) )
759
786
expectEqual ( b [ r... ] , ArraySlice ( a. filter ( f) ) )
787
+
788
+ b = a
789
+ r = b. stablePartition ( isSuffixElement: notf)
790
+ expectEqual ( b [ ..< r] , ArraySlice ( a. filter ( f) ) )
791
+ expectEqual ( b [ r... ] , ArraySlice ( a. filter ( notf) ) )
760
792
}
761
793
}
762
794
}
0 commit comments