Commit 5ea24a8b authored by Temujin's avatar Temujin

rewrote family tree and person classes

parent 1d86bec5
"""Family Tree project for CSCI 30.""" """Family Tree project for CSCI 30."""
"""
TODO:
Don't initialize with root.
Find a way to get root afterwards.
Find a way to get isolated nodes.
current structure:
bin tree inside a dict
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:
How does a dict compare object keys?
How to deal with multiple trees?
Is there only one root?
Total nodes of the tree?
11 generations = 2^11 - 1
KEY = NAME????
MAKE THE KEY ONLY THE PERSON'S NAME
MAKE HELPER FUNC
REWRITE EVERYTHING
How do class variables work?
"""
class FamilyTree: class FamilyTree:
"""A family tree. """A family tree.
Family Tree dict format -- Family Tree dict format --
key = person key = name of the person
value = [name of child1, name of child2, name of parent] value = a Person object
""" """
""" def __init__(self):
TODO: """Initialize the family tree."""
Don't initialize with root. self.family_tree = dict()
Find a way to get root afterwards. self.root = None
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:
How does a dict compare object keys?
How to deal with multiple trees?
Is there only one root?
""" def find_root(self):
"""Find the root of the tree.
def __init__(self, root): note: work in progress
"""Initialize the family tree. Start from arbitrary node,
then move upwards. (doesn't check for multiple roots)
root: the name of the first generation person. or ?????
go through every object in the dictionary
and check if it has a parent (slow)
""" """
self.family_tree = dict() return
self.root = root
self.family_tree[root] = [None, None, None] def set_root(self, person):
"""Set the root node."""
def insert_person(self, person, parent): self.root = person.get_name()
"""Add a person as a child to some parent."""
try: def insert_person(self, person):
parent_list = self.family_tree[parent] """Add a Person object to the dict with the name as the key."""
except KeyError: self.family_tree[person.get_name()] = person
raise KeyError("Error: The parent is not in the tree.")
if parent_list[1] is None: def get_person(self, name):
parent_list[1] = person """Get the named Person object from the dict."""
parent_list[person] = [None, None, parent] return self.family_tree[name]
elif parent_list[2] is None:
parent_list[2] = person
parent_list[person] = [None, None, parent]
else:
raise ValueError("Error: That parent already has two children.")
def get_ancestors(self, name): def get_ancestors(self, name):
"""Return a list of all the ancestors of a person.""" """Return a sorted list of the person's ancestors."""
person = self.family_tree[name]
parent = person.get_parent()
ancestors = [] ancestors = []
parent = self.family_tree[name][2]
while parent is not None: while parent is not None:
ancestors += parent ancestors.append(parent.get_name())
parent = self.family_tree[parent][2] parent = parent.get_parent()
ancestors.sort()
return ancestors return ancestors
def get_descendants(self, name): def get_descendants(self, name):
"""Return a list of a person's descendants.""" """Return a sorted list of a person's descendants."""
def get_preorder(person):
"""Get the inorder traversal given a person as the root."""
res = []
if person is not None:
lc, rc = person.get_children()
res.append(person.get_name())
res += get_preorder(lc)
res += get_preorder(rc)
return res
descendants = get_preorder(self.family_tree[name])[1:]
descendants.sort()
return descendants
def __str__(self):
"""Return the name."""
return self.name
class Person: class Person:
"""A person. """The nodes of the family tree.
Attributes -- Attributes --
Name: a string indicating the name name: a string indicating the name
Age: a integer indicating the age age: an integer indicating the age
Sex: a boolean, male = True, female = False sex: a boolean; male = True, female = False
children: a list of the children
parent: the parent
""" """
def __init__(self, name, age, sex): def __init__(self, name, age, sex):
"""Initialize the Person class.""" """Initialize the Person object."""
self.name = name self.name = name
self.age = age self.age = age
self.sex = sex self.sex = sex
self.children = [None, None]
self.parent = None
def set_parent(self, parent):
"""Set parent.
Also sets the current node as the parent's child.
"""
self.parent = parent
self.parent.add_child(self)
def get_parent(self):
"""Get parent."""
return self.parent
def add_child(self, child):
"""Add a child.
If there are already 2 children, raises error.
"""
if self.children[0] is None:
self.children[0] = child
elif self.children[1] is None:
self.children[1] = child
else:
raise Exception("This node already has two children.")
def get_children(self):
"""Return a list of the children."""
return self.children
def set_name(self, name): def set_name(self, name):
"""Set name.""" """Set name."""
...@@ -109,3 +180,18 @@ class Person: ...@@ -109,3 +180,18 @@ class Person:
def get_sex(self): def get_sex(self):
"""Get sex (bool).""" """Get sex (bool)."""
return self.sex return self.sex
if __name__ == "__main__":
ftree = FamilyTree()
A = Person("A", 69, True)
B = Person("B", 69, True)
C = Person("C", 69, True)
B.set_parent(A)
C.set_parent(A)
ftree.insert_person(A)
ftree.insert_person(B)
ftree.insert_person(C)
ftree.set_root(A)
print(ftree.get_ancestors(C.get_name()))
print(ftree.get_descendants(A.get_name()))
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