Skip to content

Commit b6ab520

Browse files
author
Chris Pilcher
committed
BFS Added tests for shortest path
1 parent abba1fa commit b6ab520

File tree

5 files changed

+121
-18
lines changed

5 files changed

+121
-18
lines changed

Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
2+
let shortestPathGraph = graph.duplicate()
3+
24
var queue = Queue<Node>()
3-
queue.enqueue(source)
4-
source.distance = 0
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6+
queue.enqueue(sourceInShortestPathsGraph)
7+
sourceInShortestPathsGraph.distance = 0
58

69
while !queue.isEmpty {
710
let current = queue.dequeue()!
@@ -14,9 +17,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1417
}
1518
}
1619

17-
print(graph.nodes)
20+
return shortestPathGraph
1821
}
19-
2022
/*:
2123
![Animated example of a breadth-first search](Animated_BFS.gif)
2224
*/
@@ -40,4 +42,5 @@ graph.addEdge(nodeC, neighbor: nodeF)
4042
graph.addEdge(nodeC, neighbor: nodeG)
4143
graph.addEdge(nodeE, neighbor: nodeH)
4244

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

Breadth-First Search/BreadthFirstSearchShortestPath.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
2+
let shortestPathGraph = graph.duplicate()
3+
24
var queue = Queue<Node>()
3-
queue.enqueue(source)
4-
source.distance = 0
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6+
queue.enqueue(sourceInShortestPathsGraph)
7+
sourceInShortestPathsGraph.distance = 0
58

69
while !queue.isEmpty {
710
let current = queue.dequeue()!
@@ -14,5 +17,5 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1417
}
1518
}
1619

17-
print(graph.nodes)
20+
return shortestPathGraph
1821
}

Breadth-First Search/README.markdown

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,13 @@ Continue until the queue is empty to calculate the shortest path to all other no
145145

146146
Here's the code:
147147
```swift
148-
func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
148+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
149+
let shortestPathGraph = graph.duplicate()
150+
149151
var queue = Queue<Node>()
150-
queue.enqueue(source)
151-
source.distance = 0
152+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
153+
queue.enqueue(sourceInShortestPathsGraph)
154+
sourceInShortestPathsGraph.distance = 0
152155

153156
while !queue.isEmpty {
154157
let current = queue.dequeue()!
@@ -161,13 +164,14 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
161164
}
162165
}
163166

164-
print(graph.nodes)
167+
return shortestPathGraph
165168
}
166169
```
167170

168171
Put this code in a playground and test it like so:
169172
```swift
170-
breadthFirstSearchShortestPath(graph, source: nodeA)
173+
let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA)
174+
print(shortestPathGraph.nodes)
171175

172176
// This will output:
173177
// Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1),
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import XCTest
2+
3+
class BreadthFirstSearchShortestPathTests: XCTestCase {
4+
5+
func testShortestPathWhenGivenTree() {
6+
let tree = Graph()
7+
let nodeA = tree.addNode("a")
8+
let nodeB = tree.addNode("b")
9+
let nodeC = tree.addNode("c")
10+
let nodeD = tree.addNode("d")
11+
let nodeE = tree.addNode("e")
12+
let nodeF = tree.addNode("f")
13+
let nodeG = tree.addNode("g")
14+
let nodeH = tree.addNode("h")
15+
tree.addEdge(nodeA, neighbor: nodeB)
16+
tree.addEdge(nodeA, neighbor: nodeC)
17+
tree.addEdge(nodeB, neighbor: nodeD)
18+
tree.addEdge(nodeB, neighbor: nodeE)
19+
tree.addEdge(nodeC, neighbor: nodeF)
20+
tree.addEdge(nodeC, neighbor: nodeG)
21+
tree.addEdge(nodeE, neighbor: nodeH)
22+
23+
let shortestPaths = breadthFirstSearchShortestPath(tree, source: nodeA)
24+
25+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0)
26+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1)
27+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 1)
28+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 2)
29+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 2)
30+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 2)
31+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2)
32+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 3)
33+
}
34+
35+
func testShortestPathWhenGivenGraph() {
36+
let graph = Graph()
37+
38+
let nodeA = graph.addNode("a")
39+
let nodeB = graph.addNode("b")
40+
let nodeC = graph.addNode("c")
41+
let nodeD = graph.addNode("d")
42+
let nodeE = graph.addNode("e")
43+
let nodeF = graph.addNode("f")
44+
let nodeG = graph.addNode("g")
45+
let nodeH = graph.addNode("h")
46+
let nodeI = graph.addNode("i")
47+
48+
graph.addEdge(nodeA, neighbor: nodeB)
49+
graph.addEdge(nodeA, neighbor: nodeH)
50+
graph.addEdge(nodeB, neighbor: nodeA)
51+
graph.addEdge(nodeB, neighbor: nodeC)
52+
graph.addEdge(nodeB, neighbor: nodeH)
53+
graph.addEdge(nodeC, neighbor: nodeB)
54+
graph.addEdge(nodeC, neighbor: nodeD)
55+
graph.addEdge(nodeC, neighbor: nodeF)
56+
graph.addEdge(nodeC, neighbor: nodeI)
57+
graph.addEdge(nodeD, neighbor: nodeC)
58+
graph.addEdge(nodeD, neighbor: nodeE)
59+
graph.addEdge(nodeD, neighbor: nodeF)
60+
graph.addEdge(nodeE, neighbor: nodeD)
61+
graph.addEdge(nodeE, neighbor: nodeF)
62+
graph.addEdge(nodeF, neighbor: nodeC)
63+
graph.addEdge(nodeF, neighbor: nodeD)
64+
graph.addEdge(nodeF, neighbor: nodeE)
65+
graph.addEdge(nodeF, neighbor: nodeG)
66+
graph.addEdge(nodeG, neighbor: nodeF)
67+
graph.addEdge(nodeG, neighbor: nodeH)
68+
graph.addEdge(nodeG, neighbor: nodeI)
69+
graph.addEdge(nodeH, neighbor: nodeA)
70+
graph.addEdge(nodeH, neighbor: nodeB)
71+
graph.addEdge(nodeH, neighbor: nodeG)
72+
graph.addEdge(nodeH, neighbor: nodeI)
73+
graph.addEdge(nodeI, neighbor: nodeC)
74+
graph.addEdge(nodeI, neighbor: nodeG)
75+
graph.addEdge(nodeI, neighbor: nodeH)
76+
77+
let shortestPaths = breadthFirstSearchShortestPath(graph, source: nodeA)
78+
79+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0)
80+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1)
81+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 2)
82+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 3)
83+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 4)
84+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 3)
85+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2)
86+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 1)
87+
XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeI.label).distance, 2)
88+
}
89+
}

Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */; };
11+
83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */; };
1112
83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; };
1213
83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */; };
1314
83F9C96A1C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */; };
@@ -22,6 +23,7 @@
2223
7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
2324
7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
2425
83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchMinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; };
26+
83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchShortestPathTests.swift; sourceTree = SOURCE_ROOT; };
2527
83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; };
2628
83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchMinimumSpanningTree.swift; path = ../BreadthFirstSearchMinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; };
2729
83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearchShortestPath.swift; path = ../BreadthFirstSearchShortestPath.swift; sourceTree = SOURCE_ROOT; };
@@ -66,12 +68,13 @@
6668
83F9C96E1C84449D00B3A87F /* Graph.swift */,
6769
83F9C96F1C84449D00B3A87F /* Node.swift */,
6870
83F9C9701C84449D00B3A87F /* Queue.swift */,
69-
83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */,
7071
83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */,
71-
83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */,
7272
83F9C9671C84437C00B3A87F /* BreadthFirstSearchShortestPath.swift */,
73-
7B2BBC941C779E7B0067B71D /* Info.plist */,
73+
83F9C9661C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift */,
74+
83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */,
75+
83AACB431C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift */,
7476
83AACB411C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift */,
77+
7B2BBC941C779E7B0067B71D /* Info.plist */,
7578
);
7679
name = Tests;
7780
path = TestsTests;
@@ -145,6 +148,7 @@
145148
isa = PBXSourcesBuildPhase;
146149
buildActionMask = 2147483647;
147150
files = (
151+
83AACB441C8456D200DDAFC7 /* BreadthFirstSearchShortestPathTests.swift in Sources */,
148152
83AACB421C844CED00DDAFC7 /* BreadthFirstSearchMinimumSpanningTreeTests.swift in Sources */,
149153
83F9C9721C84449D00B3A87F /* Graph.swift in Sources */,
150154
83F9C9691C84437C00B3A87F /* BreadthFirstSearchMinimumSpanningTree.swift in Sources */,

0 commit comments

Comments
 (0)