2121//
2222
2323import 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+ }
2447
2548//////////////////////////////////////
2649// MARK: Main algorithm
2750//////////////////////////////////////
2851
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+ */
3363
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+ }
3581
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+ }
3985
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
4191}
4292
4393//////////////////////////////////////
4494// MARK: Distributor
4595//////////////////////////////////////
4696
4797public protocol Distributor {
48- func distribute< T: Sortable > ( element: T , buckets: inout [ Bucket < T > ] )
98+ func distribute< T> ( _ element: T , buckets: inout [ Bucket < T > ] )
4999}
50100
51101/*
@@ -64,24 +114,24 @@ public protocol Distributor {
64114 * By following the formula: element / capacity = #ofBucket
65115 */
66116public 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+ }
77127}
78128
79129//////////////////////////////////////
80130// MARK: Sortable
81131//////////////////////////////////////
82132
83133public protocol IntConvertible {
84- func toInt( ) -> Int
134+ func toInt( ) -> Int
85135}
86136
87137public protocol Sortable : IntConvertible , Comparable {
@@ -92,50 +142,51 @@ public protocol Sortable: IntConvertible, Comparable {
92142//////////////////////////////////////
93143
94144public protocol Sorter {
95- func sort< T: Sortable > ( items: [ T ] ) -> [ T ]
145+ func sort< T: Sortable > ( _ items: [ T ] ) -> [ T ]
96146}
97147
98148public 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
114166 }
115- return results
116- }
117167}
118168
119169//////////////////////////////////////
120170// MARK: Bucket
121171//////////////////////////////////////
122172
123173public 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)
135190 }
136- }
137-
138- public func sort( algorithm: Sorter ) -> [ T ] {
139- return algorithm. sort ( items: elements)
140- }
141191}
192+
0 commit comments