Skip to content

Commit a0794ba

Browse files
authored
Merge pull request kodecocodes#343 from gonini/master
Updating Shortest Path (Unweighted) to Swift 3
2 parents cc42dc1 + a56a63c commit a0794ba

File tree

11 files changed

+155
-157
lines changed

11 files changed

+155
-157
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ script:
3737
# - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests
3838
- xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests
3939
# - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests
40-
# - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests
40+
- xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests
4141
# - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests
4242
- xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests
4343
- xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests

Shortest Path (Unweighted)/README.markdown

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,37 @@ The root of the tree is the node you started the breadth-first search from. To f
2323
Let's put breadth-first search into practice and calculate the shortest path from `A` to all the other nodes. We start with the source node `A` and add it to a queue with a distance of `0`.
2424

2525
```swift
26-
queue.enqueue(A)
26+
queue.enqueue(element: A)
2727
A.distance = 0
2828
```
2929

3030
The queue is now `[ A ]`. We dequeue `A` and enqueue its two immediate neighbor nodes `B` and `C` with a distance of `1`.
3131

3232
```swift
3333
queue.dequeue() // A
34-
queue.enqueue(B)
34+
queue.enqueue(element: B)
3535
B.distance = A.distance + 1 // result: 1
36-
queue.enqueue(C)
36+
queue.enqueue(element: C)
3737
C.distance = A.distance + 1 // result: 1
3838
```
3939

4040
The queue is now `[ B, C ]`. Dequeue `B` and enqueue `B`'s neighbor nodes `D` and `E` with a distance of `2`.
4141

4242
```swift
4343
queue.dequeue() // B
44-
queue.enqueue(D)
44+
queue.enqueue(element: D)
4545
D.distance = B.distance + 1 // result: 2
46-
queue.enqueue(E)
46+
queue.enqueue(element: E)
4747
E.distance = B.distance + 1 // result: 2
4848
```
4949

5050
The queue is now `[ C, D, E ]`. Dequeue `C` and enqueue `C`'s neighbor nodes `F` and `G`, also with a distance of `2`.
5151

5252
```swift
5353
queue.dequeue() // C
54-
queue.enqueue(F)
54+
queue.enqueue(element: F)
5555
F.distance = C.distance + 1 // result: 2
56-
queue.enqueue(G)
56+
queue.enqueue(element: G)
5757
G.distance = C.distance + 1 // result: 2
5858
```
5959

@@ -66,15 +66,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
6666
let shortestPathGraph = graph.duplicate()
6767

6868
var queue = Queue<Node>()
69-
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
70-
queue.enqueue(sourceInShortestPathsGraph)
69+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label)
70+
queue.enqueue(element: sourceInShortestPathsGraph)
7171
sourceInShortestPathsGraph.distance = 0
7272

7373
while let current = queue.dequeue() {
7474
for edge in current.neighbors {
7575
let neighborNode = edge.neighbor
7676
if !neighborNode.hasDistance {
77-
queue.enqueue(neighborNode)
77+
queue.enqueue(element: neighborNode)
7878
neighborNode.distance = current.distance! + 1
7979
}
8080
}
@@ -87,7 +87,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
8787
Put this code in a playground and test it like so:
8888

8989
```swift
90-
let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA)
90+
let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA)
9191
print(shortestPathGraph.nodes)
9292
```
9393

Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
22
let shortestPathGraph = graph.duplicate()
33

44
var queue = Queue<Node>()
5-
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6-
queue.enqueue(sourceInShortestPathsGraph)
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label)
6+
queue.enqueue(element: sourceInShortestPathsGraph)
77
sourceInShortestPathsGraph.distance = 0
88

99
while let current = queue.dequeue() {
1010
for edge in current.neighbors {
1111
let neighborNode = edge.neighbor
1212
if !neighborNode.hasDistance {
13-
queue.enqueue(neighborNode)
13+
queue.enqueue(element: neighborNode)
1414
neighborNode.distance = current.distance! + 1
1515
}
1616
}
@@ -23,14 +23,14 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
2323

2424
let graph = Graph()
2525

26-
let nodeA = graph.addNode("a")
27-
let nodeB = graph.addNode("b")
28-
let nodeC = graph.addNode("c")
29-
let nodeD = graph.addNode("d")
30-
let nodeE = graph.addNode("e")
31-
let nodeF = graph.addNode("f")
32-
let nodeG = graph.addNode("g")
33-
let nodeH = graph.addNode("h")
26+
let nodeA = graph.addNode(label: "a")
27+
let nodeB = graph.addNode(label: "b")
28+
let nodeC = graph.addNode(label: "c")
29+
let nodeD = graph.addNode(label: "d")
30+
let nodeE = graph.addNode(label: "e")
31+
let nodeF = graph.addNode(label: "f")
32+
let nodeG = graph.addNode(label: "g")
33+
let nodeH = graph.addNode(label: "h")
3434

3535
graph.addEdge(nodeA, neighbor: nodeB)
3636
graph.addEdge(nodeA, neighbor: nodeC)
@@ -40,5 +40,5 @@ graph.addEdge(nodeC, neighbor: nodeF)
4040
graph.addEdge(nodeC, neighbor: nodeG)
4141
graph.addEdge(nodeE, neighbor: nodeH)
4242

43-
let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA)
43+
let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA)
4444
print(shortestPathGraph.nodes)

Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline

Lines changed: 0 additions & 6 deletions
This file was deleted.

Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class Graph: CustomStringConvertible, Equatable {
1111
return node
1212
}
1313

14-
public func addEdge(source: Node, neighbor: Node) {
14+
public func addEdge(_ source: Node, neighbor: Node) {
1515
let edge = Edge(neighbor: neighbor)
1616
source.neighbors.append(edge)
1717
}
@@ -35,13 +35,13 @@ public class Graph: CustomStringConvertible, Equatable {
3535
let duplicated = Graph()
3636

3737
for node in nodes {
38-
duplicated.addNode(node.label)
38+
duplicated.addNode(label: node.label)
3939
}
4040

4141
for node in nodes {
4242
for edge in node.neighbors {
43-
let source = duplicated.findNodeWithLabel(node.label)
44-
let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label)
43+
let source = duplicated.findNodeWithLabel(label: node.label)
44+
let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label)
4545
duplicated.addEdge(source, neighbor: neighbour)
4646
}
4747
}

Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class Node: CustomStringConvertible, Equatable {
2323
}
2424

2525
public func remove(edge: Edge) {
26-
neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!)
26+
neighbors.remove(at: neighbors.index { $0 === edge }!)
2727
}
2828
}
2929

Shortest Path (Unweighted)/ShortestPath.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
22
let shortestPathGraph = graph.duplicate()
33

44
var queue = Queue<Node>()
5-
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6-
queue.enqueue(sourceInShortestPathsGraph)
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label)
6+
queue.enqueue(element: sourceInShortestPathsGraph)
77
sourceInShortestPathsGraph.distance = 0
88

99
while let current = queue.dequeue() {
1010
for edge in current.neighbors {
1111
let neighborNode = edge.neighbor
1212
if !neighborNode.hasDistance {
13-
queue.enqueue(neighborNode)
13+
queue.enqueue(element: neighborNode)
1414
neighborNode.distance = current.distance! + 1
1515
}
1616
}
Lines changed: 83 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,107 @@
11
// MARK: - Edge
22

3-
public class Edge: Equatable {
4-
public var neighbor: Node
5-
6-
public init(neighbor: Node) {
7-
self.neighbor = neighbor
8-
}
3+
open class Edge: Equatable {
4+
open var neighbor: Node
5+
6+
public init(neighbor: Node) {
7+
self.neighbor = neighbor
8+
}
99
}
1010

1111
public func == (lhs: Edge, rhs: Edge) -> Bool {
12-
return lhs.neighbor == rhs.neighbor
12+
return lhs.neighbor == rhs.neighbor
1313
}
1414

15-
// MARK: - Node
16-
17-
public class Node: CustomStringConvertible, Equatable {
18-
public var neighbors: [Edge]
19-
20-
public private(set) var label: String
21-
public var distance: Int?
22-
public var visited: Bool
2315

24-
public init(label: String) {
25-
self.label = label
26-
neighbors = []
27-
visited = false
28-
}
16+
// MARK: - Node
2917

30-
public var description: String {
31-
if let distance = distance {
32-
return "Node(label: \(label), distance: \(distance))"
18+
open class Node: CustomStringConvertible, Equatable {
19+
open var neighbors: [Edge]
20+
21+
open fileprivate(set) var label: String
22+
open var distance: Int?
23+
open var visited: Bool
24+
25+
public init(label: String) {
26+
self.label = label
27+
neighbors = []
28+
visited = false
29+
}
30+
31+
open var description: String {
32+
if let distance = distance {
33+
return "Node(label: \(label), distance: \(distance))"
34+
}
35+
return "Node(label: \(label), distance: infinity)"
36+
}
37+
38+
open var hasDistance: Bool {
39+
return distance != nil
40+
}
41+
42+
open func remove(_ edge: Edge) {
43+
neighbors.remove(at: neighbors.index { $0 === edge }!)
3344
}
34-
return "Node(label: \(label), distance: infinity)"
35-
}
36-
37-
public var hasDistance: Bool {
38-
return distance != nil
39-
}
40-
41-
public func remove(edge: Edge) {
42-
neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!)
43-
}
4445
}
4546

4647
public func == (lhs: Node, rhs: Node) -> Bool {
47-
return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors
48+
return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors
4849
}
4950

5051
// MARK: - Graph
5152

52-
public class Graph: CustomStringConvertible, Equatable {
53-
public private(set) var nodes: [Node]
54-
55-
public init() {
56-
self.nodes = []
57-
}
58-
59-
public func addNode(label: String) -> Node {
60-
let node = Node(label: label)
61-
nodes.append(node)
62-
return node
63-
}
64-
65-
public func addEdge(source: Node, neighbor: Node) {
66-
let edge = Edge(neighbor: neighbor)
67-
source.neighbors.append(edge)
68-
}
69-
70-
public var description: String {
71-
var description = ""
72-
73-
for node in nodes {
74-
if !node.neighbors.isEmpty {
75-
description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]"
76-
}
53+
open class Graph: CustomStringConvertible, Equatable {
54+
open fileprivate(set) var nodes: [Node]
55+
56+
public init() {
57+
self.nodes = []
7758
}
78-
return description
79-
}
80-
81-
public func findNodeWithLabel(label: String) -> Node {
82-
return nodes.filter { $0.label == label }.first!
83-
}
84-
85-
public func duplicate() -> Graph {
86-
let duplicated = Graph()
87-
88-
for node in nodes {
89-
duplicated.addNode(node.label)
59+
60+
open func addNode(label: String) -> Node {
61+
let node = Node(label: label)
62+
nodes.append(node)
63+
return node
9064
}
91-
92-
for node in nodes {
93-
for edge in node.neighbors {
94-
let source = duplicated.findNodeWithLabel(node.label)
95-
let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label)
96-
duplicated.addEdge(source, neighbor: neighbour)
97-
}
65+
66+
open func addEdge(_ source: Node, neighbor: Node) {
67+
let edge = Edge(neighbor: neighbor)
68+
source.neighbors.append(edge)
69+
}
70+
71+
open var description: String {
72+
var description = ""
73+
74+
for node in nodes {
75+
if !node.neighbors.isEmpty {
76+
description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]"
77+
}
78+
}
79+
return description
80+
}
81+
82+
open func findNodeWithLabel(label: String) -> Node {
83+
return nodes.filter { $0.label == label }.first!
84+
}
85+
86+
open func duplicate() -> Graph {
87+
let duplicated = Graph()
88+
89+
for node in nodes {
90+
duplicated.addNode(label: node.label)
91+
}
92+
93+
for node in nodes {
94+
for edge in node.neighbors {
95+
let source = duplicated.findNodeWithLabel(label: node.label)
96+
let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label)
97+
duplicated.addEdge(source, neighbor: neighbour)
98+
}
99+
}
100+
101+
return duplicated
98102
}
99-
100-
return duplicated
101-
}
102103
}
103104

104105
public func == (lhs: Graph, rhs: Graph) -> Bool {
105-
return lhs.nodes == rhs.nodes
106+
return lhs.nodes == rhs.nodes
106107
}

Shortest Path (Unweighted)/Tests/Queue.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
public struct Queue<T> {
2-
private var array: [T]
2+
fileprivate var array: [T]
33

44
public init() {
55
array = []

0 commit comments

Comments
 (0)