21
21
//
22
22
23
23
import Foundation
24
+ // FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
25
+ // Consider refactoring the code to use the non-optional operators.
26
+ fileprivate func < < T: Comparable > ( lhs: T ? , rhs: T ? ) -> Bool {
27
+ switch ( lhs, rhs) {
28
+ case let ( l? , r? ) :
29
+ return l < r
30
+ case ( nil , _? ) :
31
+ return true
32
+ default :
33
+ return false
34
+ }
35
+ }
36
+
37
+ // FIXME: comparison operators with optionals were removed from the Swift Standard Libary.
38
+ // Consider refactoring the code to use the non-optional operators.
39
+ fileprivate func >= < T: Comparable > ( lhs: T ? , rhs: T ? ) -> Bool {
40
+ switch ( lhs, rhs) {
41
+ case let ( l? , r? ) :
42
+ return l >= r
43
+ default :
44
+ return !( lhs < rhs)
45
+ }
46
+ }
24
47
25
48
//////////////////////////////////////
26
49
// MARK: Main algorithm
27
50
//////////////////////////////////////
28
51
29
- public func bucketSort< T: Sortable > ( elements: [ T ] , distributor: Distributor , sorter: Sorter , buckets: inout [ Bucket < T > ] ) -> [ T ] {
30
- for elem in elements {
31
- distributor. distribute ( element: elem, buckets: & buckets)
32
- }
52
+ /**
53
+ Performs bucket sort algorithm on the given input elements.
54
+ [Bucket Sort Algorithm Reference](https://en.wikipedia.org/wiki/Bucket_sort)
55
+
56
+ - Parameter elements: Array of Sortable elements
57
+ - Parameter distributor: Performs the distribution of each element of a bucket
58
+ - Parameter sorter: Performs the sorting inside each bucket, after all the elements are distributed
59
+ - Parameter buckets: An array of buckets
60
+
61
+ - Returns: A new array with sorted elements
62
+ */
33
63
34
- var results = [ T] ( )
64
+ public func bucketSort< T> ( _ elements: [ T ] , distributor: Distributor , sorter: Sorter , buckets: [ Bucket < T > ] ) -> [ T ] {
65
+ precondition ( allPositiveNumbers ( elements) )
66
+ precondition ( enoughSpaceInBuckets ( buckets, elements: elements) )
67
+
68
+ var bucketsCopy = buckets
69
+ for elem in elements {
70
+ distributor. distribute ( elem, buckets: & bucketsCopy)
71
+ }
72
+
73
+ var results = [ T] ( )
74
+
75
+ for bucket in bucketsCopy {
76
+ results += bucket. sort ( sorter)
77
+ }
78
+
79
+ return results
80
+ }
35
81
36
- for bucket in buckets {
37
- results += bucket . sort ( algorithm : sorter )
38
- }
82
+ private func allPositiveNumbers < T : Sortable > ( _ array : [ T ] ) -> Bool {
83
+ return array . filter { $0 . toInt ( ) >= 0 } . count > 0
84
+ }
39
85
40
- return results
86
+ private func enoughSpaceInBuckets< T> ( _ buckets: [ Bucket < T > ] , elements: [ T ] ) -> Bool {
87
+ let maximumValue = elements. max ( ) ? . toInt ( )
88
+ let totalCapacity = buckets. count * ( buckets. first? . capacity) !
89
+
90
+ return totalCapacity >= maximumValue
41
91
}
42
92
43
93
//////////////////////////////////////
44
94
// MARK: Distributor
45
95
//////////////////////////////////////
46
96
47
97
public protocol Distributor {
48
- func distribute< T: Sortable > ( element: T , buckets: inout [ Bucket < T > ] )
98
+ func distribute< T> ( _ element: T , buckets: inout [ Bucket < T > ] )
49
99
}
50
100
51
101
/*
@@ -64,24 +114,24 @@ public protocol Distributor {
64
114
* By following the formula: element / capacity = #ofBucket
65
115
*/
66
116
public struct RangeDistributor : Distributor {
67
-
68
- public init ( ) { }
69
-
70
- public func distribute< T: Sortable > ( element: T , buckets: inout [ Bucket < T > ] ) {
71
- let value = element. toInt ( )
72
- let bucketCapacity = buckets. first!. capacity
73
-
74
- let bucketIndex = value / bucketCapacity
75
- buckets [ bucketIndex] . add ( item : element)
76
- }
117
+
118
+ public init ( ) { }
119
+
120
+ public func distribute< T> ( _ element: T , buckets: inout [ Bucket < T > ] ) {
121
+ let value = element. toInt ( )
122
+ let bucketCapacity = buckets. first!. capacity
123
+
124
+ let bucketIndex = value / bucketCapacity
125
+ buckets [ bucketIndex] . add ( element)
126
+ }
77
127
}
78
128
79
129
//////////////////////////////////////
80
130
// MARK: Sortable
81
131
//////////////////////////////////////
82
132
83
133
public protocol IntConvertible {
84
- func toInt( ) -> Int
134
+ func toInt( ) -> Int
85
135
}
86
136
87
137
public protocol Sortable : IntConvertible , Comparable {
@@ -92,50 +142,51 @@ public protocol Sortable: IntConvertible, Comparable {
92
142
//////////////////////////////////////
93
143
94
144
public protocol Sorter {
95
- func sort< T: Sortable > ( items: [ T ] ) -> [ T ]
145
+ func sort< T: Sortable > ( _ items: [ T ] ) -> [ T ]
96
146
}
97
147
98
148
public struct InsertionSorter : Sorter {
99
-
100
- public init ( ) { }
101
-
102
- public func sort< T: Sortable > ( items: [ T ] ) -> [ T ] {
103
- var results = items
104
- for i in 0 ..< results. count {
105
- var j = i
106
- while j > 0 && results [ j- i] > results [ j] {
107
-
108
- let auxiliar = results [ i]
109
- results [ i] = results [ j]
110
- results [ j] = auxiliar
111
-
112
- j -= 1
113
- }
149
+
150
+ public init ( ) { }
151
+
152
+ public func sort< T: Sortable > ( _ items: [ T ] ) -> [ T ] {
153
+ var results = items
154
+ for i in 0 ..< results. count {
155
+ var j = i
156
+ while j > 0 && results [ j- 1 ] > results [ j] {
157
+
158
+ let auxiliar = results [ j- 1 ]
159
+ results [ j- 1 ] = results [ j]
160
+ results [ j] = auxiliar
161
+
162
+ j -= 1
163
+ }
164
+ }
165
+ return results
114
166
}
115
- return results
116
- }
117
167
}
118
168
119
169
//////////////////////////////////////
120
170
// MARK: Bucket
121
171
//////////////////////////////////////
122
172
123
173
public struct Bucket < T: Sortable > {
124
- var elements : [ T ]
125
- let capacity : Int
126
-
127
- public init ( capacity: Int ) {
128
- self . capacity = capacity
129
- elements = [ T] ( )
130
- }
131
-
132
- public mutating func add( item: T ) {
133
- if elements. count < capacity {
134
- elements. append ( item)
174
+ var elements : [ T ]
175
+ let capacity : Int
176
+
177
+ public init ( capacity: Int ) {
178
+ self . capacity = capacity
179
+ elements = [ T] ( )
180
+ }
181
+
182
+ public mutating func add( _ item: T ) {
183
+ if elements. count < capacity {
184
+ elements. append ( item)
185
+ }
186
+ }
187
+
188
+ public func sort( _ algorithm: Sorter ) -> [ T ] {
189
+ return algorithm. sort ( elements)
135
190
}
136
- }
137
-
138
- public func sort( algorithm: Sorter ) -> [ T ] {
139
- return algorithm. sort ( items: elements)
140
- }
141
191
}
192
+
0 commit comments