Skip to content

Commit 91e39bc

Browse files
authored
Merge pull request kodecocodes#281 from divyenduz/migrate_bucket_sort
Bucket sort migration to swift 3
2 parents 85b05cf + 30dd3a0 commit 91e39bc

File tree

7 files changed

+66
-43
lines changed

7 files changed

+66
-43
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ script:
1616
- xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests
1717
# - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests
1818
# - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests
19-
# - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests
19+
- xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests
2020
- xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests
2121
# - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests
2222
# - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests

Bucket Sort/BucketSort.playground/Contents.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
//
2121
//
2222

23-
24-
25-
2623
//////////////////////////////////////
2724
// MARK: Extensions
2825
//////////////////////////////////////
@@ -38,8 +35,8 @@ extension Int: IntConvertible, Sortable {
3835
//////////////////////////////////////
3936

4037
let input = [1, 2, 4, 6, 10]
41-
let buckets = [Bucket<Int>(capacity: 15), Bucket<Int>(capacity: 15), Bucket<Int>(capacity: 15)]
38+
var buckets = [Bucket<Int>(capacity: 15), Bucket<Int>(capacity: 15), Bucket<Int>(capacity: 15)]
4239

43-
let sortedElements = bucketSort(input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets)
40+
let sortedElements = bucketSort(elements: input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: &buckets)
4441

4542
print(sortedElements)

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,15 @@ import Foundation
2727
//////////////////////////////////////
2828

2929

30-
public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket<T>]) -> [T] {
31-
var bucketsCopy = buckets
30+
public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sorter: Sorter, buckets: inout [Bucket<T>]) -> [T] {
3231
for elem in elements {
33-
distributor.distribute(elem, buckets: &bucketsCopy)
32+
distributor.distribute(element: elem, buckets: &buckets)
3433
}
3534

3635
var results = [T]()
3736

3837
for bucket in buckets {
39-
results += bucket.sort(sorter)
38+
results += bucket.sort(algorithm: sorter)
4039
}
4140

4241
return results
@@ -48,7 +47,7 @@ public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sor
4847

4948

5049
public protocol Distributor {
51-
func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>])
50+
func distribute<T: Sortable>(element: T, buckets: inout [Bucket<T>])
5251
}
5352

5453
/*
@@ -70,12 +69,12 @@ public struct RangeDistributor: Distributor {
7069

7170
public init() {}
7271

73-
public func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>]) {
72+
public func distribute<T: Sortable>(element: T, buckets: inout [Bucket<T>]) {
7473
let value = element.toInt()
7574
let bucketCapacity = buckets.first!.capacity
7675

7776
let bucketIndex = value / bucketCapacity
78-
buckets[bucketIndex].add(element)
77+
buckets[bucketIndex].add(item: element)
7978
}
8079
}
8180

@@ -139,6 +138,6 @@ public struct Bucket<T:Sortable> {
139138
}
140139

141140
public func sort(algorithm: Sorter) -> [T] {
142-
return algorithm.sort(elements)
141+
return algorithm.sort(items: elements)
143142
}
144143
}

Bucket Sort/BucketSort.swift

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,30 @@
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+
}
47+
2448

2549
//////////////////////////////////////
2650
// MARK: Main algorithm
@@ -39,7 +63,7 @@ import Foundation
3963
- Returns: A new array with sorted elements
4064
*/
4165

42-
public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket<T>]) -> [T] {
66+
public func bucketSort<T: Sortable>(_ elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket<T>]) -> [T] {
4367
precondition(allPositiveNumbers(elements))
4468
precondition(enoughSpaceInBuckets(buckets, elements: elements))
4569

@@ -57,12 +81,12 @@ public func bucketSort<T: Sortable>(elements: [T], distributor: Distributor, sor
5781
return results
5882
}
5983

60-
private func allPositiveNumbers<T: Sortable>(array: [T]) -> Bool {
84+
private func allPositiveNumbers<T: Sortable>(_ array: [T]) -> Bool {
6185
return array.filter { $0.toInt() >= 0 }.count > 0
6286
}
6387

64-
private func enoughSpaceInBuckets<T: Sortable>(buckets: [Bucket<T>], elements: [T]) -> Bool {
65-
let maximumValue = elements.maxElement()?.toInt()
88+
private func enoughSpaceInBuckets<T: Sortable>(_ buckets: [Bucket<T>], elements: [T]) -> Bool {
89+
let maximumValue = elements.max()?.toInt()
6690
let totalCapacity = buckets.count * (buckets.first?.capacity)!
6791

6892
return totalCapacity >= maximumValue
@@ -74,7 +98,7 @@ private func enoughSpaceInBuckets<T: Sortable>(buckets: [Bucket<T>], elements: [
7498

7599

76100
public protocol Distributor {
77-
func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>])
101+
func distribute<T: Sortable>(_ element: T, buckets: inout [Bucket<T>])
78102
}
79103

80104
/*
@@ -96,7 +120,7 @@ public struct RangeDistributor: Distributor {
96120

97121
public init() {}
98122

99-
public func distribute<T: Sortable>(element: T, inout buckets: [Bucket<T>]) {
123+
public func distribute<T: Sortable>(_ element: T, buckets: inout [Bucket<T>]) {
100124
let value = element.toInt()
101125
let bucketCapacity = buckets.first!.capacity
102126

@@ -121,14 +145,14 @@ public protocol Sortable: IntConvertible, Comparable {
121145
//////////////////////////////////////
122146

123147
public protocol Sorter {
124-
func sort<T: Sortable>(items: [T]) -> [T]
148+
func sort<T: Sortable>(_ items: [T]) -> [T]
125149
}
126150

127151
public struct InsertionSorter: Sorter {
128152

129153
public init() {}
130154

131-
public func sort<T: Sortable>(items: [T]) -> [T] {
155+
public func sort<T: Sortable>(_ items: [T]) -> [T] {
132156
var results = items
133157
for i in 0 ..< results.count {
134158
var j = i
@@ -158,13 +182,13 @@ public struct Bucket<T:Sortable> {
158182
elements = [T]()
159183
}
160184

161-
public mutating func add(item: T) {
185+
public mutating func add(_ item: T) {
162186
if elements.count < capacity {
163187
elements.append(item)
164188
}
165189
}
166190

167-
public func sort(algorithm: Sorter) -> [T] {
191+
public func sort(_ algorithm: Sorter) -> [T] {
168192
return algorithm.sort(elements)
169193
}
170194
}

Bucket Sort/README.markdown

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ Bucket Sort, also known as Bin Sort, is a distributed sorting algorithm, which s
99
See the algorithm in action [here](https://www.cs.usfca.edu/~galles/visualization/BucketSort.html) and [here](http://www.algostructure.com/sorting/bucketsort.php).
1010

1111
The performance for execution time is:
12-
12+
1313
| Case | Performance |
1414
|:-------------: |:---------------:|
1515
| Worst | O(n^2) |
1616
| Best | Omega(n + k) |
17-
| Average | Theta(n + k) |
18-
17+
| Average | Theta(n + k) |
18+
1919
Where **n** = the number of elements and **k** is the number of buckets.
2020

21-
In the *best case*, the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list.
21+
In the *best case*, the algorithm distributes the elements uniformly between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list.
2222

2323
In the *worst case*, the elements are sent all to the same bucket, making the process take **O(n^2)**.
2424

@@ -63,11 +63,11 @@ So the buckets are:
6363
Now we need to choose a distribution function.
6464

6565
`bucketNumber = (elementValue / totalNumberOfBuckets) + 1`
66-
66+
6767
Such that by applying that function we distribute all the elements in the buckets.
6868

6969
In our example it is like the following:
70-
70+
7171
1. Apply the distribution function to `2`. `bucketNumber = (2 / 10) + 1 = 1`
7272
2. Apply the distribution function to `56`. `bucketNumber = (56 / 10) + 1 = 6`
7373
3. Apply the distribution function to `4`. `bucketNumber = (4 / 10) + 1 = 1`
@@ -91,12 +91,12 @@ Our buckets will be filled now:
9191

9292
We can choose to insert the elements in every bucket in order, or sort every bucket after distributing all the elements.
9393

94-
### Put the elements back in the list
94+
### Put the elements back in the list
9595

9696
Finally we go through all the buckets and put the elements back in the list:
97-
97+
9898
`[2, 4, 26, 55, 56, 77, 98]`
99-
99+
100100

101101
## Swift implementation
102102

@@ -109,9 +109,9 @@ Here is a diagram that shows the functions, data structures and protocols for ou
109109
`bucketSort()` is a generic function that can apply the algorithm to any element of type `T`, as long as `T` is `Sortable`.
110110

111111
```swift
112-
public func bucketSort<T:Sortable>(elements: [T],
113-
distributor: Distributor,
114-
sorter: Sorter,
112+
public func bucketSort<T:Sortable>(elements: [T],
113+
distributor: Distributor,
114+
sorter: Sorter,
115115
buckets: [Bucket<T>]) -> [T] {
116116
precondition(allPositiveNumbers(elements))
117117
precondition(enoughSpaceInBuckets(buckets, elements: elements))
@@ -201,11 +201,11 @@ public struct InsertionSorter: Sorter {
201201
for i in 0 ..< results.count {
202202
var j = i
203203
while ( j > 0 && results[j-1] > results[j]) {
204-
204+
205205
let auxiliar = results[j-1]
206206
results[j-1] = results[j]
207207
results[j] = auxiliar
208-
208+
209209
j -= 1
210210
}
211211
}
@@ -236,7 +236,7 @@ public struct RangeDistributor: Distributor {
236236
public func distribute<T:Sortable>(element: T, inout buckets: [Bucket<T>]) {
237237
let value = element.toInt()
238238
let bucketCapacity = buckets.first!.capacity
239-
239+
240240
let bucketIndex = value / bucketCapacity
241241
buckets[bucketIndex].add(element)
242242
}

Bucket Sort/Tests/Tests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class TestTests: XCTestCase {
2525

2626
largeArray = [Int]()
2727
for _ in 0..<total {
28-
largeArray!.append( random() % maximum )
28+
largeArray!.append( Int(arc4random_uniform( UInt32( maximum ) ) ) )
2929
}
3030

3131
sparsedArray = [Int]()
@@ -57,9 +57,9 @@ class TestTests: XCTestCase {
5757

5858
// MARK: Private functions
5959

60-
private func performBucketSort(elements: [Int], totalBuckets: Int) -> [Int] {
60+
fileprivate func performBucketSort(_ elements: [Int], totalBuckets: Int) -> [Int] {
6161

62-
let value = (elements.maxElement()?.toInt())! + 1
62+
let value = (elements.max()?.toInt())! + 1
6363
let capacityRequired = Int( ceil( Double(value) / Double(totalBuckets) ) )
6464

6565
var buckets = [Bucket<Int>]()
@@ -71,7 +71,7 @@ class TestTests: XCTestCase {
7171
return results
7272
}
7373

74-
func isSorted(array: [Int]) -> Bool {
74+
func isSorted(_ array: [Int]) -> Bool {
7575

7676
var index = 0
7777
var sorted = true

Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
TargetAttributes = {
8989
7B2BBC7F1C779D720067B71D = {
9090
CreatedOnToolsVersion = 7.2;
91+
LastSwiftMigration = 0810;
9192
};
9293
};
9394
};
@@ -222,6 +223,7 @@
222223
PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests;
223224
PRODUCT_NAME = "$(TARGET_NAME)";
224225
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
226+
SWIFT_VERSION = 3.0;
225227
};
226228
name = Debug;
227229
};
@@ -234,6 +236,7 @@
234236
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
235237
PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests;
236238
PRODUCT_NAME = "$(TARGET_NAME)";
239+
SWIFT_VERSION = 3.0;
237240
};
238241
name = Release;
239242
};

0 commit comments

Comments
 (0)