From a6bff78fb65cc50f56b53c4bd3018b5fd4e78708 Mon Sep 17 00:00:00 2001 From: Jaap Date: Thu, 22 Sep 2016 02:52:40 +0200 Subject: [PATCH] updated Ordered Set to swift 3 --- .../Example 1.xcplaygroundpage/Contents.swift | 2 +- .../timeline.xctimeline | 21 ++++++++++ .../Example 2.xcplaygroundpage/Contents.swift | 2 +- .../Example 3.xcplaygroundpage/Contents.swift | 6 +-- .../timeline.xctimeline | 6 +++ .../Sources/OrderedSet.swift | 24 +++++------ .../Sources/Player.swift | 2 +- .../Sources/Random.swift | 2 +- Ordered Set/README.markdown | 40 +++++++++---------- 9 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline create mode 100644 Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift index c1fe6fe11..2420019fc 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift @@ -4,7 +4,7 @@ var mySet = OrderedSet() // Insert random numbers into the set for _ in 0..<50 { - mySet.insert(random(50, max: 500)) + mySet.insert(random(min: 50, max: 500)) } print(mySet) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..454d1011b --- /dev/null +++ b/Ordered Set/OrderedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift index 6fc1f66ed..c30260fff 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift @@ -23,7 +23,7 @@ print(playerSet.max()) print(playerSet.min()) // We'll find our player now: -let level = playerSet.count - playerSet.indexOf(anotherPlayer)! +let level = playerSet.count - playerSet.index(of: anotherPlayer)! print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.points) points") //: [Next](@next) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift index 872b5aeb4..52f154c05 100644 --- a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift +++ b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift @@ -17,6 +17,6 @@ repeatedSet.insert(Player(name: "Player 9", points: 25)) print(repeatedSet) //debugPrint(repeatedSet) -print(repeatedSet.indexOf(Player(name: "Player 5", points: 100))) -print(repeatedSet.indexOf(Player(name: "Random Player", points: 100))) -print(repeatedSet.indexOf(Player(name: "Player 5", points: 1000))) +print(repeatedSet.index(of: Player(name: "Player 5", points: 100))) +print(repeatedSet.index(of: Player(name: "Random Player", points: 100))) +print(repeatedSet.index(of: Player(name: "Player 5", points: 1000))) diff --git a/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift b/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift index a8b3b0966..8490a3320 100644 --- a/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift +++ b/Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift @@ -14,7 +14,7 @@ public struct OrderedSet { } // Inserts an item. Performance: O(n) - public mutating func insert(item: T) { + public mutating func insert(_ item: T) { if exists(item) { return // don't add an item if it already exists } @@ -22,7 +22,7 @@ public struct OrderedSet { // Insert new the item just before the one that is larger. for i in 0.. item { - internalSet.insert(item, atIndex: i) + internalSet.insert(item, at: i) return } } @@ -32,19 +32,19 @@ public struct OrderedSet { } // Removes an item if it exists. Performance: O(n) - public mutating func remove(item: T) { - if let index = indexOf(item) { - internalSet.removeAtIndex(index) + public mutating func remove(_ item: T) { + if let index = index(of: item) { + internalSet.remove(at: index) } } // Returns true if and only if the item exists somewhere in the set. - public func exists(item: T) -> Bool { - return indexOf(item) != nil + public func exists(_ item: T) -> Bool { + return index(of: item) != nil } // Returns the index of an item if it exists, or -1 otherwise. - public func indexOf(item: T) -> Int? { + public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 @@ -64,7 +64,7 @@ public struct OrderedSet { // and to the left in order to find an exact match. // Check to the right. - for j in mid.stride(to: count - 1, by: 1) { + for j in stride(from: mid, to: count - 1, by: 1) { if internalSet[j + 1] == item { return j + 1 } else if internalSet[j] < internalSet[j + 1] { @@ -73,7 +73,7 @@ public struct OrderedSet { } // Check to the left. - for j in mid.stride(to: 0, by: -1) { + for j in stride(from: mid, to: 0, by: -1) { if internalSet[j - 1] == item { return j - 1 } else if internalSet[j] > internalSet[j - 1] { @@ -105,13 +105,13 @@ public struct OrderedSet { // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kLargest(k: Int) -> T? { + public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kSmallest(k: Int) -> T? { + public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } } diff --git a/Ordered Set/OrderedSet.playground/Sources/Player.swift b/Ordered Set/OrderedSet.playground/Sources/Player.swift index 9357744db..26835b0a8 100644 --- a/Ordered Set/OrderedSet.playground/Sources/Player.swift +++ b/Ordered Set/OrderedSet.playground/Sources/Player.swift @@ -6,7 +6,7 @@ public struct Player: Comparable { public init() { self.name = String.random() - self.points = random(0, max: 5000) + self.points = random(min: 0, max: 5000) } public init(name: String, points: Int) { diff --git a/Ordered Set/OrderedSet.playground/Sources/Random.swift b/Ordered Set/OrderedSet.playground/Sources/Random.swift index b6e1f7736..eccd65df6 100644 --- a/Ordered Set/OrderedSet.playground/Sources/Random.swift +++ b/Ordered Set/OrderedSet.playground/Sources/Random.swift @@ -13,7 +13,7 @@ extension String { for _ in 0.. { Lets take a look at the `insert()` function first. This first checks if the item already exists in the collection. If so, it returns and does not insert the item. Otherwise, it will insert the item through straightforward iteration. ```swift - public mutating func insert(item: T){ + public mutating func insert(_ item: T){ if exists(item) { return // don't add an item if it already exists } @@ -63,7 +63,7 @@ Lets take a look at the `insert()` function first. This first checks if the item // Insert new the item just before the one that is larger. for i in 0.. item { - internalSet.insert(item, atIndex: i) + internalSet.insert(item, at: i) return } } @@ -82,19 +82,19 @@ The total performance of the `insert()` function is therefore **O(n)**. Next up is the `remove()` function: ```swift - public mutating func remove(item: T) { - if let index = indexOf(item) { - internalSet.removeAtIndex(index) + public mutating func remove(_ item: T) { + if let index = index(of: item) { + internalSet.remove(at: index) } } ``` First this checks if the item exists and then removes it from the array. Because of the `removeAtIndex()` function, the efficiency for remove is **O(n)**. -The next function is `indexOf()`, which takes in an object of type `T` and returns the index of the corresponding item if it is in the set, or `nil` if it is not. Since our set is sorted, we can use a binary search to quickly search for the item. +The next function is `indexOf()`, which takes in an object of type `T` and returns the index of the corresponding item if it is in the set, or `nil` if it is not. Since our set is sorted, we can use a binary search to quickly search for the item. ```swift - public func indexOf(item: T) -> Int? { + public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 @@ -115,9 +115,9 @@ The next function is `indexOf()`, which takes in an object of type `T` and retur } ``` -> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). +> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). -However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. +However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. For example, consider this ordered set of `Player` objects. Each `Player` has a name and a number of points: @@ -147,13 +147,13 @@ Therefore, we also need to check the items with the same value to the right and break } } - + return nil ``` These loops start at the current `mid` value and then look at the neighboring values until we've found the correct object. -The combined runtime for `indexOf()` is **O(log(n) + k)** where **n** is the length of the set, and **k** is the number of items with the same *value* as the one that is being searched for. +The combined runtime for `indexOf()` is **O(log(n) + k)** where **n** is the length of the set, and **k** is the number of items with the same *value* as the one that is being searched for. Since the set is sorted, the following operations are all **O(1)**: @@ -168,15 +168,15 @@ Since the set is sorted, the following operations are all **O(1)**: return count == 0 ? nil : internalSet[0] } - // Returns the k-th largest element in the set, if k is in the range + // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kLargest(k: Int) -> T? { + public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. - public func kSmallest(k: Int) -> T? { + public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } ``` @@ -228,7 +228,7 @@ public struct Player: Comparable { The `Player` also gets its own `==` and `<` operators. The `<` operator is used to determine the sort order of the set, while `==` determines whether two objects are really equal. Note that `==` compares both the name and the points: - + ```swifr func ==(x: Player, y: Player) -> Bool { return x.name == y.name && x.points == y.points @@ -272,7 +272,7 @@ print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.po ### Example 3 -The final example demonstrates the need to look for the right item even after the binary search has completed. +The final example demonstrates the need to look for the right item even after the binary search has completed. We insert 9 players into the set: @@ -299,7 +299,7 @@ The set looks something like this: The next line looks for `Player 2`: ```swift -print(repeatedSet.indexOf(Player(name: "Player 2", points: 100))) +print(repeatedSet.index(of: Player(name: "Player 2", points: 100))) ``` After the binary search finishes, the value of `mid` is at index 5: @@ -312,7 +312,7 @@ However, this is not `Player 2`. Both `Player 4` and `Player 2` have the same po But we do know that `Player 2` must be either to the immediate left or the right of `Player 4`, so we check both sides of `mid`. We only need to look at the objects with the same value as `Player 4`. The others are replaced by `X`: [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] - mid + mid The code then first checks on the right of `mid` (where the `*` is):