Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
CSCI30_Project
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Marc Yap
CSCI30_Project
Commits
62e7d090
Commit
62e7d090
authored
Dec 05, 2019
by
Temujin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finished relationship method
parent
9541f220
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
95 additions
and
25 deletions
+95
-25
family_tree.py
family_tree.py
+95
-25
No files found.
family_tree.py
View file @
62e7d090
"""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__"
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment