Skip to content

Commit b791a4f

Browse files
committed
Merge pull request kodecocodes#88 from zainh96/master
Implementing Ordered Set
2 parents 0871bc9 + 7be8994 commit b791a4f

File tree

5 files changed

+718
-1
lines changed

5 files changed

+718
-1
lines changed
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
// random function returns a random number between the given range
2+
func randomNum(min: Int, max: Int) -> Int {
3+
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
4+
}
5+
6+
// extension for String generates a random alphanumeric string of length 8
7+
extension String {
8+
static func random(length: Int = 8) -> String {
9+
10+
let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
11+
var randomString: String = ""
12+
13+
for _ in 0..<length {
14+
let randomValue = arc4random_uniform(UInt32(base.characters.count))
15+
randomString += "\(base[base.startIndex.advancedBy(Int(randomValue))])"
16+
}
17+
18+
return randomString
19+
}
20+
}
21+
22+
// Player data type stores a random name, and a random number of points from 0 - 5000
23+
struct Player : Comparable {
24+
var name: String! = String.random()
25+
var points = randomNum(0, max: 5000)
26+
27+
init(name: String, points: Int){
28+
self.name = name
29+
self.points = points
30+
}
31+
32+
init(){}
33+
}
34+
35+
// == operator for struct Player
36+
// Player x is equal to Player y if and only if both players have the same name and number of points
37+
func ==(x: Player, y: Player) -> Bool {
38+
return x.name == y.name && x.points == y.points
39+
}
40+
41+
// < operator for struct Player
42+
// Player x is less than Player y if and only if x has less points than y
43+
func <(x: Player, y: Player) -> Bool {
44+
return x.points < y.points
45+
}
46+
47+
// prints a Player formatted with their name and number of points
48+
func print(player: Player){
49+
print("Player: \(player.name) | Points: \(player.points)")
50+
}
51+
52+
func print(set: OrderedSet<Player>){
53+
for i in 0..<set.count {
54+
print(set[set.count - i - 1])
55+
}
56+
}
57+
58+
import Foundation
59+
60+
// An Ordered Set is a collection where all items in the set follow an ordering, usually ordered from
61+
// 'least' to 'most'. The way you value, and compare items can be user defined.
62+
public struct OrderedSet<T: Comparable> {
63+
private var internalSet: [T]! = nil
64+
65+
// returns size of Set
66+
public var count: Int {
67+
return internalSet!.count
68+
}
69+
70+
public init(){
71+
internalSet = [T]() // create the internal array on init
72+
}
73+
74+
// inserts an item
75+
// O(n log n)
76+
public mutating func insert(item: T){
77+
if exists(item) {
78+
return // don't add an item if it already exists
79+
}
80+
81+
for i in 0..<count {
82+
if internalSet[i] > item {
83+
internalSet.insert(item, atIndex: i)
84+
return
85+
}
86+
}
87+
88+
// if an item is larger than any item in the current set, append it to the back.
89+
internalSet.append(item)
90+
}
91+
92+
// removes an item if it exists
93+
public mutating func remove(item: T) {
94+
if !exists(item) {
95+
return
96+
}
97+
98+
internalSet.removeAtIndex(findIndex(item))
99+
}
100+
101+
// returns true if and only if the item exists somewhere in the set
102+
public func exists(item: T) -> Bool {
103+
let index = findIndex(item)
104+
return index != -1
105+
}
106+
107+
// returns the index of an item if it exists, otherwise returns -1.
108+
public func findIndex(item: T) -> Int {
109+
var leftBound = 0
110+
var rightBound = count - 1
111+
112+
while leftBound <= rightBound {
113+
let mid = leftBound + ((rightBound - leftBound) / 2)
114+
115+
if internalSet[mid] > item {
116+
rightBound = mid - 1
117+
} else if internalSet[mid] < item {
118+
leftBound = mid + 1
119+
} else {
120+
// check the mid value to see if it is the item we are looking for
121+
if internalSet[mid] == item {
122+
return mid
123+
}
124+
125+
var j = mid
126+
127+
// check right side of mid
128+
while j < internalSet.count - 1 && !(internalSet[j] < internalSet[j + 1]) {
129+
if internalSet[j + 1] == item {
130+
return j + 1
131+
}
132+
133+
j += 1
134+
}
135+
136+
j = mid
137+
138+
// check left side of mid
139+
while j > 0 && !(internalSet[j] < internalSet[j - 1]) {
140+
if internalSet[j - 1] == item {
141+
return j - 1
142+
}
143+
144+
j -= 1
145+
}
146+
return -1
147+
}
148+
}
149+
150+
return -1
151+
}
152+
153+
// returns the item at the given index. assertion fails if the index is out of the range
154+
// of [0, count)
155+
public subscript(index: Int) -> T {
156+
assert(index >= 0 && index < count)
157+
return internalSet[index]
158+
}
159+
160+
// returns the 'maximum' or 'largest' value in the set
161+
public func max() -> T! {
162+
return count == 0 ? nil : internalSet[count - 1]
163+
}
164+
165+
// returns the 'minimum' or 'smallest' value in the set
166+
public func min() -> T! {
167+
return count == 0 ? nil : internalSet[0]
168+
}
169+
170+
// returns the k largest element in the set, if k is in the range [1, count]
171+
// returns nil otherwise
172+
public func kLargest(k: Int) -> T! {
173+
return k > count || k <= 0 ? nil : internalSet[count - k]
174+
}
175+
176+
// returns the k smallest element in the set, if k is in the range [1, count]
177+
// returns nil otherwise
178+
public func kSmallest(k: Int) -> T! {
179+
return k > count || k <= 0 ? nil : internalSet[k - 1]
180+
}
181+
}
182+
183+
// Example 1 with type Int
184+
var mySet = OrderedSet<Int>()
185+
186+
// insert random ints into the set
187+
188+
for _ in 0..<50 {
189+
mySet.insert(randomNum(50, max: 500))
190+
}
191+
192+
print(mySet)
193+
194+
print(mySet.max())
195+
print(mySet.min())
196+
197+
// print the 5 largest values
198+
for k in 1..<6 {
199+
print(mySet.kLargest(k))
200+
}
201+
202+
// print the 5 lowest values
203+
for k in 1..<6 {
204+
print(mySet.kSmallest(k))
205+
}
206+
207+
208+
// Example 2 with type Player
209+
var playerSet = OrderedSet<Player>()
210+
211+
// populate with random players.
212+
var anotherPlayer = Player()
213+
for _ in 0..<20 {
214+
playerSet.insert(Player())
215+
}
216+
217+
// we'll look for this player later
218+
playerSet.insert(anotherPlayer)
219+
220+
// print all players in order
221+
print(playerSet)
222+
223+
224+
// highest and lowest players:
225+
print(playerSet.max())
226+
print(playerSet.min())
227+
228+
// we'll find our player now
229+
print("'Another Player (\(anotherPlayer.name))' is ranked at level: \(playerSet.count - playerSet.findIndex(anotherPlayer)) with \(anotherPlayer.points) points")
230+
231+
232+
233+
// Example with multiple entries with the same value
234+
235+
var repeatedSet = OrderedSet<Player>()
236+
237+
repeatedSet.insert(Player(name:"Player 1", points: 100))
238+
repeatedSet.insert(Player(name: "Player 1", points: 100))
239+
repeatedSet.insert(Player(name: "Player 2", points: 100))
240+
repeatedSet.insert(Player(name: "Player 3", points: 100))
241+
repeatedSet.insert(Player(name: "Player 4", points: 100))
242+
repeatedSet.insert(Player(name: "Player 5", points: 100))
243+
repeatedSet.insert(Player(name: "Player 6", points: 50))
244+
repeatedSet.insert(Player(name: "Player 7", points: 200))
245+
repeatedSet.insert(Player(name: "Player 8", points: 250))
246+
repeatedSet.insert(Player(name: "Player 9", points: 25))
247+
248+
print(repeatedSet)
249+
250+
// find player 5
251+
print(repeatedSet.findIndex(Player(name: "Player 5", points: 100)))
252+
print(repeatedSet.findIndex(Player(name: "Random Player", points: 100)))
253+
print(repeatedSet.findIndex(Player(name: "Player 5", points: 1000)))
254+
255+
256+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>

Ordered Set/OrderedSet.swift

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// An Ordered Set is a collection where all items in the set follow an ordering, usually ordered from
2+
// 'least' to 'most'. The way you value, and compare items can be user defined.
3+
public struct OrderedSet<T: Comparable> {
4+
private var internalSet: [T]! = nil
5+
6+
// returns size of Set
7+
public var count: Int {
8+
return internalSet!.count
9+
}
10+
11+
public init(){
12+
internalSet = [T]() // create the internal array on init
13+
}
14+
15+
// inserts an item
16+
// O(n log n)
17+
public mutating func insert(item: T){
18+
if exists(item) {
19+
return // don't add an item if it already exists
20+
}
21+
22+
for i in 0..<count {
23+
if internalSet[i] > item {
24+
internalSet.insert(item, atIndex: i)
25+
return
26+
}
27+
}
28+
29+
// if an item is larger than any item in the current set, append it to the back.
30+
internalSet.append(item)
31+
}
32+
33+
// removes an item if it exists
34+
public mutating func remove(item: T) {
35+
if !exists(item) {
36+
return
37+
}
38+
39+
internalSet.removeAtIndex(findIndex(item))
40+
}
41+
42+
// returns true if and only if the item exists somewhere in the set
43+
public func exists(item: T) -> Bool {
44+
let index = findIndex(item)
45+
return index != -1
46+
}
47+
48+
// returns the index of an item if it exists, otherwise returns -1.
49+
public func findIndex(item: T) -> Int {
50+
var leftBound = 0
51+
var rightBound = count - 1
52+
53+
while leftBound <= rightBound {
54+
let mid = leftBound + ((rightBound - leftBound) / 2)
55+
56+
if internalSet[mid] > item {
57+
rightBound = mid - 1
58+
} else if internalSet[mid] < item {
59+
leftBound = mid + 1
60+
} else {
61+
// check the mid value to see if it is the item we are looking for
62+
if internalSet[mid] == item {
63+
return mid
64+
}
65+
66+
var j = mid
67+
68+
// check right side of mid
69+
while j < internalSet.count - 1 && !(internalSet[j] < internalSet[j + 1]) {
70+
if internalSet[j + 1] == item {
71+
return j + 1
72+
}
73+
74+
j += 1
75+
}
76+
77+
j = mid
78+
79+
// check left side of mid
80+
while j > 0 && !(internalSet[j] < internalSet[j - 1]) {
81+
if internalSet[j - 1] == item {
82+
return j - 1
83+
}
84+
85+
j -= 1
86+
}
87+
return -1
88+
}
89+
}
90+
91+
return -1
92+
}
93+
94+
// returns the item at the given index. assertion fails if the index is out of the range
95+
// of [0, count)
96+
public subscript(index: Int) -> T {
97+
assert(index >= 0 && index < count)
98+
return internalSet[index]
99+
}
100+
101+
// returns the 'maximum' or 'largest' value in the set
102+
public func max() -> T! {
103+
return count == 0 ? nil : internalSet[count - 1]
104+
}
105+
106+
// returns the 'minimum' or 'smallest' value in the set
107+
public func min() -> T! {
108+
return count == 0 ? nil : internalSet[0]
109+
}
110+
111+
// returns the k largest element in the set, if k is in the range [1, count]
112+
// returns nil otherwise
113+
public func kLargest(k: Int) -> T! {
114+
return k > count || k <= 0 ? nil : internalSet[count - k]
115+
}
116+
117+
// returns the k smallest element in the set, if k is in the range [1, count]
118+
// returns nil otherwise
119+
public func kSmallest(k: Int) -> T! {
120+
return k > count || k <= 0 ? nil : internalSet[k - 1]
121+
}
122+
}

0 commit comments

Comments
 (0)