Commit 5970f441 authored by Temujin's avatar Temujin

added somee tests

parent 2c60a6d3
......@@ -18,8 +18,7 @@ class FamilyTree:
1 get all the nodes and edges, check if they're valid.
2 Make sure there's only one root.
3 Find and set the root
4 Set the generations
5 run precompute method
5 run set_generations() method
6 done
"""
......@@ -41,12 +40,15 @@ class FamilyTree:
Note: Will not work if there's more than one node without a parent
"""
arbitrary_node = next(iter(self.family_tree.values()))
try:
arbitrary_node = next(iter(self.family_tree.values()))
while arbitrary_node.get_parent() is not None:
arbitrary_node = arbitrary_node.get_parent()
while arbitrary_node.get_parent() is not None:
arbitrary_node = arbitrary_node.get_parent()
self.root = arbitrary_node
self.root = arbitrary_node
except StopIteration:
print("The tree is empty.")
def insert_person(self, person):
"""Add a Person object to the dict with the name as the key."""
......@@ -83,15 +85,8 @@ class FamilyTree:
descendants.sort()
return descendants
def precompute(self):
"""Do the precomputations necessary to find LCA and degree.
DFS from root. (todo)
Along the way, set the generations (levels)
and fill up the arrays for the lca query (TODO)
Raises exception if a root cannot be found.
"""
def set_generations(self):
"""Set the generations of the node by doing DFS."""
def set_gen(node):
"""Set the generation of a node to be one more than its parent."""
if node.parent is not None:
......@@ -99,11 +94,6 @@ class FamilyTree:
else:
node.set_generation(1)
def pre_lca(node):
# TODO
self.dfs_order.append(node.get_name())
self.dfs_gen.append(node.get_generation())
if self.root is None:
self.find_root()
if self.root is None:
......@@ -113,10 +103,8 @@ class FamilyTree:
def dfs(self, s, *funcs):
"""Depth first search from s, doing the given functions on each node.
S = name of person in starting node.
s = name of person in starting node.
*funcs = the operations to be done on the node
#TODO FIX THIS
"""
visited = []
current_node = self.family_tree[s]
......@@ -135,10 +123,6 @@ class FamilyTree:
self.dfs(rc.get_name(), *funcs)
def find_lca(self, name1, name2):
"""Find the lowest common ancestor of two nodes."""
return self.slow_lca(name1, name2)
def slow_lca(self, name1, name2):
"""Find the lca slowly.
Two pointer method.
......@@ -161,13 +145,6 @@ class FamilyTree:
p2 = p2.get_parent()
return p1
def fast_lca(self, a, b):
"""Find the lca fast.
Reduction to range min. query
"""
return
def relationship(self, p1, p2):
"""Determine the relationship between two distinct people in the tree.
......@@ -197,7 +174,9 @@ class FamilyTree:
elif furthest == 2:
return self.TERM("nibling", d1, d2, p2.sex)
else:
return self.GREAT(furthest-2) + "grand" + self.TERM("nibling", d1, d2, p2.sex)
# SPECIAL CASES: grand-niece/nephew, grand-aunt/uncle.
num_greats = abs(p1.get_generation() - p2.get_generation()) - 2
return self.GREAT(num_greats) + "grand" + self.TERM("nibling", d1, d2, p2.sex)
elif nearest == 0:
if furthest == 1:
return self.TERM("child", d1, d2, p2.sex)
......@@ -355,7 +334,7 @@ def openfile(filename):
p2.set_parent(p1)
readF.close()
atree.precompute()
atree.set_generations()
return atree
......@@ -384,7 +363,7 @@ def savefile(filename, tree):
saveF.write("child " + parent.get_name() + " " + x.get_name() + "\n")
def commandLine():
def command_line():
"""Open command line."""
tree = FamilyTree()
while True:
......@@ -461,7 +440,7 @@ def commandLine():
print("Error: File not found")
elif cmd[0] == "save":
tree.find_root()
tree.precompute()
tree.set_generations()
savefile(cmd[1], tree)
print("file saved")
elif cmd[0] == "bye":
......@@ -472,66 +451,17 @@ def commandLine():
def main():
r"""For testing.
A
/ \
B C
/ \
D E
"""
ftree = FamilyTree()
A = Person("A", 69, True)
B = Person("B", 69, True)
C = Person("C", 69, False)
D = Person("D", 69, True)
E = Person("E", 666, False)
ftree.insert_person(A)
ftree.insert_person(B)
ftree.insert_person(C)
ftree.insert_person(D)
ftree.insert_person(E)
B.set_parent(A)
C.set_parent(A)
D.set_parent(B)
E.set_parent(B)
ftree.find_root()
ancestors = ftree.get_ancestors(D.get_name())
descendants = ftree.get_descendants(A.get_name())
print("The root of the tree is {}.".format(ftree.root))
print("ancestors of {}: {}".format("D", ancestors))
print("descendants of {}: {}".format("A", descendants))
ftree.precompute()
for key, node in ftree.family_tree.items():
print("{}: {}".format(node, node.get_generation()))
print("The lca of {} and {} is {}".format(D, C, ftree.find_lca("D", "C")))
print("The lca of {} and {} is {}".format(B, D, ftree.find_lca("B", "D")))
print("The lca of {} and {} is {}".format(A, B, ftree.find_lca("A", "B")))
# parent/child
print("{} is {}'s: {}".format(B, A, ftree.relationship(A, B)))
print("{} is {}'s: {}".format(A, B, ftree.relationship(B, A)))
# grandparent/granchild
print("")
# sibling
print("{} is {}'s: {}".format(B, C, ftree.relationship(C, B)))
print("{} is {}'s: {}".format(C, B, ftree.relationship(B, C)))
# nibling
print("{} is {}'s: {}".format(D, C, ftree.relationship(C, D)))
print("{} is {}'s: {}".format(C, D, ftree.relationship(D, C)))
print("{} is {}'s: {}".format(A, D, ftree.relationship(D, A)))
print("{} is {}'s: {}".format(D, A, ftree.relationship(A, D)))
# test for opening and saving files
ntree = openfile("chandelier")
ntree.find_root()
ntree.precompute()
ntree.set_generations()
print("The root of the tree is {}.".format(ntree.root))
for key, node in ntree.family_tree.items():
print("{}: {}".format(node, node.get_generation()))
savefile("test", ntree)
command_line()
if __name__ == "__main__":
......
Files Included:
family_tree.py
Minimum specs:
Processors: Intel Atom® processor or Intel® Core™ i3 processor
Disk space: 1 GB
Operating systems: Windows* 7 or later, macOS
Python* versions: 3.6.X
Special cases:
The lca of two people x and y, if x is an ancestor of y, is x.
lca(x, y) = x
Although not really the "lowest common ancestor", since a node is not
an ancestor of itself, this implementation was chosen to make it work
with the pseudocode for the relationship function.
How to start the program:
Open terminal:
> python family_tree.py
import sys
import os
sys.path.insert(0, os.path.abspath(
os.path.join(os.path.dirname(__file__), '..')))
import family_tree
import context as c
"""Unittest for family_tree."""
import sys
import os
sys.path.insert(0, os.path.abspath(
os.path.join(os.path.dirname(__file__), '..')))
import family_tree as f
import unittest
class TestFamilyTree(unittest.TestCase):
"""For testing family tree."""
def setUp(self):
r"""For testing.
Test tree:
A
/ \
B C
/ \
D E
/
F
"""
self.ftree = c.FamilyTree()
ftree = c.FamilyTree()
A = c.Person("A", 69, True)
B = c.Person("B", 69, True)
C = c.Person("C", 69, False)
D = c.Person("D", 69, True)
E = c.Person("E", 666, False)
ftree.insert_person(A)
ftree.insert_person(B)
ftree.insert_person(C)
ftree.insert_person(D)
ftree.insert_person(E)
self.ftree = f.FamilyTree()
A = f.Person("A", 69, True)
B = f.Person("B", 69, True)
C = f.Person("C", 69, False)
D = f.Person("D", 69, True)
E = f.Person("E", 666, False)
F = f.Person("F", 420, False)
self.ftree.insert_person(A)
self.ftree.insert_person(B)
self.ftree.insert_person(C)
self.ftree.insert_person(D)
self.ftree.insert_person(E)
self.ftree.insert_person(F)
self.assertGreater(len(self.ftree.family_tree), 0)
B.set_parent(A)
C.set_parent(A)
D.set_parent(B)
E.set_parent(B)
ftree.find_root()
F.set_parent(D)
self.ftree.find_root()
def test_find_ancestors(self):
pass
D_ancestors = self.ftree.get_ancestors("D")
r = set(["B", "A"])
self.assertEqual(set(D_ancestors), r)
root_ancestor = self.ftree.get_ancestors("A")
self.assertListEqual(root_ancestor, [])
def test_find_descendants(self):
pass
root_descendants = set(self.ftree.get_descendants("A"))
r = set(self.ftree.family_tree.keys()) - {"A"}
self.assertEqual(root_descendants, r)
leaf_descendants = self.ftree.get_descendants("F")
self.assertListEqual(leaf_descendants, [])
def test_set_generations(self):
pass
self.ftree.set_generations()
for name, person in self.ftree.family_tree.items():
self.assertFalse(person.get_generation() is None)
def test_lca(self):
self.ftree.set_generations()
lca1 = self.ftree.find_lca("D", "C")
lca2 = self.ftree.find_lca("B", "D")
lca3 = self.ftree.find_lca("A", "B")
A = self.ftree.get_person("A")
B = self.ftree.get_person("B")
self.assertEqual(lca1, A)
self.assertEqual(lca2, B)
self.assertEqual(lca3, A)
def test_relationship(self):
self.ftree.set_generations()
A = self.ftree.get_person("A")
B = self.ftree.get_person("B")
C = self.ftree.get_person("C")
D = self.ftree.get_person("D")
F = self.ftree.get_person("F")
# parent/child
self.assertEqual(self.ftree.relationship(A, B), "son")
self.assertEqual(self.ftree.relationship(B, A), "father")
# grand parent/child
self.assertEqual(self.ftree.relationship(A, D), "grandson")
self.assertEqual(self.ftree.relationship(D, A), "grandfather")
# great grandparent/child
self.assertEqual(self.ftree.relationship(F, A), "greatgrandfather")
self.assertEqual(self.ftree.relationship(A, F), "greatgranddaughter")
# sibling
self.assertEqual(self.ftree.relationship(C, B), "brother")
self.assertEqual(self.ftree.relationship(B, C), "sister")
# nibling
self.assertEqual(self.ftree.relationship(C, D), "nephew")
self.assertEqual(self.ftree.relationship(D, C), "aunt")
# grand nibling
self.assertEqual
self.assertEqual(self.ftree.relationship(C, F), "grandniece")
self.assertEqual(self.ftree.relationship(F, C), "grandaunt")
if __name__ == "__main__":
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment