-
Notifications
You must be signed in to change notification settings - Fork 19
/
4.7-Build_Order.py
67 lines (52 loc) · 1.94 KB
/
4.7-Build_Order.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# CTCI 4.7
# Build Order
# My Solution
def build_order(projects, dependencies):
adj_list = {}
in_deg = {}
no_edges = []
result = []
# Go thru projects and appropriately initilaize the adj list
for project in projects:
adj_list[project] = []
in_deg[project] = 0
# Go thru dependencies and construct the graph with the adj list
for first, second in dependencies:
adj_list[first].append(second)
in_deg[second] += 1
# Find all the nodes with no incoming edges
for project in in_deg:
if in_deg[project] == 0:
no_edges.append(project)
# Loop through all projects with no incoming edges
while no_edges:
node = no_edges.pop()
# Loop through projects that the current node has an outgoing edge to
for project in adj_list[node]:
# Remove 1 from it's dependencies
in_deg[project] -= 1
# If the dependencies were fulfilled, add to no_edges
if in_deg[project] == 0:
no_edges.append(project)
result.append(node)
# If all the projects can be completed in a order
if len(result) == len(projects):
return result
else:
return None
#-------------------------------------------------------------------------------
#Testing
import unittest
class Test(unittest.TestCase):
def test_build_order(self):
projects = ["A", "B", "C", "D", "E", "F", "G"]
dependencies1 = [("C", "A"), ("B", "A"), ("F", "A"), ("F", "B"), ("F", "C"),
("A", "E"), ("B", "E"), ("D", "G")]
print(build_order(projects, dependencies1))
dependencies2 = [("A", "B"), ("B", "C"), ("C", "D"), ("D", "A")]
print(build_order(projects, dependencies2))
dependencies3 = [("A", "B"), ("A", "C"), ("E", "A"), ("E", "B"), ("A", "F"),
("B", "F"), ("C", "F"), ("G", "D")]
print(build_order(projects, dependencies3))
if __name__ == "__main__":
unittest.main()