Skip to content

Commit 689efb3

Browse files
committed
[Swift 4] Update Bucket Search
1 parent 06d3ef3 commit 689efb3

File tree

1 file changed

+107
-59
lines changed

1 file changed

+107
-59
lines changed

Bucket Sort/BucketSort.playground/Sources/BucketSort.swift

Lines changed: 107 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,81 @@
2121
//
2222

2323
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+
}
2447

2548
//////////////////////////////////////
2649
// MARK: Main algorithm
2750
//////////////////////////////////////
2851

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+
*/
2963

30-
public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket<T>]) -> [T] {
31-
var bucketsCopy = buckets
32-
for elem in elements {
33-
distributor.distribute(elem, buckets: &bucketsCopy)
34-
}
35-
36-
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+
}
3781

38-
for bucket in buckets {
39-
results += bucket.sort(sorter)
40-
}
82+
private func allPositiveNumbers<T: Sortable>(_ array: [T]) -> Bool {
83+
return array.filter { $0.toInt() >= 0 }.count > 0
84+
}
4185

42-
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
4391
}
4492

4593
//////////////////////////////////////
4694
// MARK: Distributor
4795
//////////////////////////////////////
4896

49-
5097
public protocol Distributor {
51-
func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>])
98+
func distribute<T>(_ element: T, buckets: inout [Bucket<T>])
5299
}
53100

54101
/*
@@ -67,24 +114,24 @@ public protocol Distributor {
67114
* By following the formula: element / capacity = #ofBucket
68115
*/
69116
public struct RangeDistributor: Distributor {
70-
71-
public init() {}
72-
73-
public func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>]) {
74-
let value = element.toInt()
75-
let bucketCapacity = buckets.first!.capacity
76-
77-
let bucketIndex = value / bucketCapacity
78-
buckets[bucketIndex].add(element)
79-
}
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+
}
80127
}
81128

82129
//////////////////////////////////////
83130
// MARK: Sortable
84131
//////////////////////////////////////
85132

86133
public protocol IntConvertible {
87-
func toInt() -> Int
134+
func toInt() -> Int
88135
}
89136

90137
public protocol Sortable: IntConvertible, Comparable {
@@ -95,50 +142,51 @@ public protocol Sortable: IntConvertible, Comparable {
95142
//////////////////////////////////////
96143

97144
public protocol Sorter {
98-
func sort<T: Sortable>(items: [T]) -> [T]
145+
func sort<T: Sortable>(_ items: [T]) -> [T]
99146
}
100147

101148
public struct InsertionSorter: Sorter {
102-
103-
public init() {}
104-
105-
public func sort<T: Sortable>(items: [T]) -> [T] {
106-
var results = items
107-
for i in 0 ..< results.count {
108-
var j = i
109-
while j > 0 && results[j-i] > results[j] {
110-
111-
let auxiliar = results[i]
112-
results[i] = results[j]
113-
results[j] = auxiliar
114-
115-
j -= 1
116-
}
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
117166
}
118-
return results
119-
}
120167
}
121168

122169
//////////////////////////////////////
123170
// MARK: Bucket
124171
//////////////////////////////////////
125172

126-
public struct Bucket<T:Sortable> {
127-
var elements: [T]
128-
let capacity: Int
129-
130-
public init(capacity: Int) {
131-
self.capacity = capacity
132-
elements = [T]()
133-
}
134-
135-
public mutating func add(item: T) {
136-
if elements.count < capacity {
137-
elements.append(item)
173+
public struct Bucket<T: Sortable> {
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)
138190
}
139-
}
140-
141-
public func sort(algorithm: Sorter) -> [T] {
142-
return algorithm.sort(elements)
143-
}
144191
}
192+

0 commit comments

Comments
 (0)