Commit 62e7d090 authored by Temujin's avatar Temujin

finished relationship method

parent 9541f220
"""Family Tree project for CSCI 30."""
"""
TODO:
Find a way to get isolated nodes.
Problems to consider --
What to do if not rooted?
Multiple roots?
What if the file describes two separate trees at once?
Handling value errors.
Incest and cycles:
> Adding someone already in the tree as a child
Problems taken care of(?) --
Adding child to someone who already has two children.
Questions:
Is there only one root?
Total nodes of the tree?
11 generations = 2^11 - 1
......@@ -30,8 +17,6 @@ Tree setup procedure:
4 Set the generations
5 run precompute method
6 done
"""
......@@ -47,6 +32,12 @@ class FamilyTree:
value = a Person object, acting as the node
"""
ordinal = ["first", "second", "third", "fourth", "fifth",
"sixth", "seventh", "eighth", "ninth", "tenth"]
times = ["once", "twice", "thrice", "four times", "five times",
"six times", "seven times", "eight times", "nine times",
"ten times"]
def __init__(self):
"""Initialize the family tree."""
self.family_tree = dict()
......@@ -106,9 +97,9 @@ class FamilyTree:
return descendants
def precompute(self):
"""Do the precomputations required to find LCA and degree.
"""Do the precomputations necessary to find LCA and degree.
DFS from root.
DFS from root. (todo)
Along the way, set the generations (levels)
and fill up the arrays for the lca query (TODO)
......@@ -137,6 +128,8 @@ class FamilyTree:
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]
......@@ -154,7 +147,7 @@ class FamilyTree:
visited.append(rc.get_name())
self.dfs(rc.get_name(), *funcs)
def lca(self, name1, name2):
def find_lca(self, name1, name2):
"""Find the lowest common ancestor of two nodes.
TODO: when one is the ancestor of the other
......@@ -183,7 +176,7 @@ class FamilyTree:
p1 = p1.get_parent()
p2 = p2.get_parent()
return p1.get_name()
return p1
def fast_lca(self, a, b):
"""Find the lca fast.
......@@ -192,10 +185,12 @@ class FamilyTree:
"""
return
def degree(self, p1, p2):
"""Find the degree between two cousins."""
l_ancestor = self.lca(p1, p2)
return min([self.lca(p1, l_ancestor), self.lca(p2, l_ancestor)])
def get_degree(self, p1, p2, lca):
"""Find the degree between two people."""
distance_p1 = lca.get_generation() - p1.get_generation()
distance_p2 = lca.get_generation() - p2.get_generation()
deg = min[distance_p1 - 1, distance_p2 - 1]
return deg
def relationship(self, p1, p2):
"""Determine the relationship between two distinct people in the tree.
......@@ -203,8 +198,79 @@ class FamilyTree:
Input: Two people p1 and p2, where p1 != p2
Output: The relationship between p1 and p2, from the perspective of p1
"""
lca = self.find_lca(p1.get_name(), p2.get_name())
d1 = p1.get_generation() - lca.get_generation()
d2 = p2.get_generation() - lca.get_generation()
nearest = min([d1, d2])
furthest = max([d1, d2])
if nearest >= 2:
degree = nearest - 1
removal = abs(d1-d2)
if removal == 0:
return self.ORDINAL(degree) + "cousin"
else:
return self.ORDINAL(degree) + "cousin " + self.TIMES(removal) + "removed"
elif nearest == 1:
if furthest == 1:
if p2.sex is True:
return "brother"
else:
return "sister"
elif furthest == 2:
return self.TERM("nibling", d1, d2, p2.sex)
else:
return self.GREAT(furthest) + "grand" + self.TERM("nibling", d1, d2, p2.sex)
elif nearest == 0:
## TODO: PARENT RELATIONSHIP
if furthest == 1:
return self.TERM("child", d1, d2, p2.sex)
else:
return self.GREAT(furthest) + "grand" + self.TERM("child", d1, d2, p2.sex)
pass
def ORDINAL(self, n):
"""Return the index in the ordinal table."""
return self.ordinal[n]
def TIMES(self, n):
"""Return the index in the times table."""
return self.times[n]
def great(self, n):
"""Return a string of n 'greats' separated by - ."""
return "-".join(["great"]*n)
def TERM(self, kind, d1, d2, sex):
"""Return the term."""
assert (d1 != d2)
if kind == "child":
if d1 < d2:
if sex is True:
return "son"
else:
return "daughter"
else:
if sex is True:
return "father"
else:
return "mother"
elif kind == "nibling":
if d1 < d2:
if sex is True:
return "nephew"
else:
return "niece"
else:
if sex is True:
return "uncle"
else:
return "aunt"
class Person:
"""The nodes of the family tree.
......@@ -325,8 +391,12 @@ def main():
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.lca("D", "C")))
print("The lca of {} and {} is {}".format(B, D, ftree.lca("B", "D")))
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")))
print("relationship (A, B): {}".format(ftree.relationship(A, B)))
print("relationship (B, C): {}".format(ftree.relationship(B, C)))
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