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
Temujin
CSCI30_Project
Commits
5970f441
Commit
5970f441
authored
Dec 11, 2019
by
Temujin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added somee tests
parent
2c60a6d3
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
126 additions
and
112 deletions
+126
-112
family_tree.cpython-36.pyc
__pycache__/family_tree.cpython-36.pyc
+0
-0
family_tree.py
family_tree.py
+19
-89
readme.txt
readme.txt
+19
-0
context.py
tests/context.py
+0
-6
ft_test.py
tests/ft_test.py
+88
-17
No files found.
__pycache__/family_tree.cpython-36.pyc
View file @
5970f441
No preview for this file type
family_tree.py
View file @
5970f441
...
@@ -18,8 +18,7 @@ class FamilyTree:
...
@@ -18,8 +18,7 @@ class FamilyTree:
1 get all the nodes and edges, check if they're valid.
1 get all the nodes and edges, check if they're valid.
2 Make sure there's only one root.
2 Make sure there's only one root.
3 Find and set the root
3 Find and set the root
4 Set the generations
5 run set_generations() method
5 run precompute method
6 done
6 done
"""
"""
...
@@ -41,12 +40,15 @@ class FamilyTree:
...
@@ -41,12 +40,15 @@ class FamilyTree:
Note: Will not work if there's more than one node without a parent
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
:
while
arbitrary_node
.
get_parent
()
is
not
None
:
arbitrary_node
=
arbitrary_node
.
get_parent
()
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
):
def
insert_person
(
self
,
person
):
"""Add a Person object to the dict with the name as the key."""
"""Add a Person object to the dict with the name as the key."""
...
@@ -83,15 +85,8 @@ class FamilyTree:
...
@@ -83,15 +85,8 @@ class FamilyTree:
descendants
.
sort
()
descendants
.
sort
()
return
descendants
return
descendants
def
precompute
(
self
):
def
set_generations
(
self
):
"""Do the precomputations necessary to find LCA and degree.
"""Set the generations of the node by doing DFS."""
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_gen
(
node
):
def
set_gen
(
node
):
"""Set the generation of a node to be one more than its parent."""
"""Set the generation of a node to be one more than its parent."""
if
node
.
parent
is
not
None
:
if
node
.
parent
is
not
None
:
...
@@ -99,11 +94,6 @@ class FamilyTree:
...
@@ -99,11 +94,6 @@ class FamilyTree:
else
:
else
:
node
.
set_generation
(
1
)
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
:
if
self
.
root
is
None
:
self
.
find_root
()
self
.
find_root
()
if
self
.
root
is
None
:
if
self
.
root
is
None
:
...
@@ -113,10 +103,8 @@ class FamilyTree:
...
@@ -113,10 +103,8 @@ class FamilyTree:
def
dfs
(
self
,
s
,
*
funcs
):
def
dfs
(
self
,
s
,
*
funcs
):
"""Depth first search from s, doing the given functions on each node.
"""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
*funcs = the operations to be done on the node
#TODO FIX THIS
"""
"""
visited
=
[]
visited
=
[]
current_node
=
self
.
family_tree
[
s
]
current_node
=
self
.
family_tree
[
s
]
...
@@ -135,10 +123,6 @@ class FamilyTree:
...
@@ -135,10 +123,6 @@ class FamilyTree:
self
.
dfs
(
rc
.
get_name
(),
*
funcs
)
self
.
dfs
(
rc
.
get_name
(),
*
funcs
)
def
find_lca
(
self
,
name1
,
name2
):
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.
"""Find the lca slowly.
Two pointer method.
Two pointer method.
...
@@ -161,13 +145,6 @@ class FamilyTree:
...
@@ -161,13 +145,6 @@ class FamilyTree:
p2
=
p2
.
get_parent
()
p2
=
p2
.
get_parent
()
return
p1
return
p1
def
fast_lca
(
self
,
a
,
b
):
"""Find the lca fast.
Reduction to range min. query
"""
return
def
relationship
(
self
,
p1
,
p2
):
def
relationship
(
self
,
p1
,
p2
):
"""Determine the relationship between two distinct people in the tree.
"""Determine the relationship between two distinct people in the tree.
...
@@ -197,7 +174,9 @@ class FamilyTree:
...
@@ -197,7 +174,9 @@ class FamilyTree:
elif
furthest
==
2
:
elif
furthest
==
2
:
return
self
.
TERM
(
"nibling"
,
d1
,
d2
,
p2
.
sex
)
return
self
.
TERM
(
"nibling"
,
d1
,
d2
,
p2
.
sex
)
else
:
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
:
elif
nearest
==
0
:
if
furthest
==
1
:
if
furthest
==
1
:
return
self
.
TERM
(
"child"
,
d1
,
d2
,
p2
.
sex
)
return
self
.
TERM
(
"child"
,
d1
,
d2
,
p2
.
sex
)
...
@@ -355,7 +334,7 @@ def openfile(filename):
...
@@ -355,7 +334,7 @@ def openfile(filename):
p2
.
set_parent
(
p1
)
p2
.
set_parent
(
p1
)
readF
.
close
()
readF
.
close
()
atree
.
precompute
()
atree
.
set_generations
()
return
atree
return
atree
...
@@ -384,7 +363,7 @@ def savefile(filename, tree):
...
@@ -384,7 +363,7 @@ def savefile(filename, tree):
saveF
.
write
(
"child "
+
parent
.
get_name
()
+
" "
+
x
.
get_name
()
+
"
\n
"
)
saveF
.
write
(
"child "
+
parent
.
get_name
()
+
" "
+
x
.
get_name
()
+
"
\n
"
)
def
command
L
ine
():
def
command
_l
ine
():
"""Open command line."""
"""Open command line."""
tree
=
FamilyTree
()
tree
=
FamilyTree
()
while
True
:
while
True
:
...
@@ -461,7 +440,7 @@ def commandLine():
...
@@ -461,7 +440,7 @@ def commandLine():
print
(
"Error: File not found"
)
print
(
"Error: File not found"
)
elif
cmd
[
0
]
==
"save"
:
elif
cmd
[
0
]
==
"save"
:
tree
.
find_root
()
tree
.
find_root
()
tree
.
precompute
()
tree
.
set_generations
()
savefile
(
cmd
[
1
],
tree
)
savefile
(
cmd
[
1
],
tree
)
print
(
"file saved"
)
print
(
"file saved"
)
elif
cmd
[
0
]
==
"bye"
:
elif
cmd
[
0
]
==
"bye"
:
...
@@ -472,66 +451,17 @@ def commandLine():
...
@@ -472,66 +451,17 @@ def commandLine():
def
main
():
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
# test for opening and saving files
ntree
=
openfile
(
"chandelier"
)
ntree
=
openfile
(
"chandelier"
)
ntree
.
find_root
()
ntree
.
find_root
()
ntree
.
precompute
()
ntree
.
set_generations
()
print
(
"The root of the tree is {}."
.
format
(
ntree
.
root
))
print
(
"The root of the tree is {}."
.
format
(
ntree
.
root
))
for
key
,
node
in
ntree
.
family_tree
.
items
():
for
key
,
node
in
ntree
.
family_tree
.
items
():
print
(
"{}: {}"
.
format
(
node
,
node
.
get_generation
()))
print
(
"{}: {}"
.
format
(
node
,
node
.
get_generation
()))
savefile
(
"test"
,
ntree
)
savefile
(
"test"
,
ntree
)
command_line
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
readme.txt
0 → 100644
View file @
5970f441
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
tests/context.py
deleted
100644 → 0
View file @
2c60a6d3
import
sys
import
os
sys
.
path
.
insert
(
0
,
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'..'
)))
import
family_tree
tests/ft_test.py
View file @
5970f441
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
import
unittest
class
TestFamilyTree
(
unittest
.
TestCase
):
class
TestFamilyTree
(
unittest
.
TestCase
):
"""For testing family tree."""
def
setUp
(
self
):
def
setUp
(
self
):
r"""For testing.
r"""For testing.
Test tree:
A
A
/
\
/
\
B C
B C
/
\
/
\
D E
D E
/
F
"""
"""
self
.
ftree
=
c
.
FamilyTree
()
self
.
ftree
=
f
.
FamilyTree
()
ftree
=
c
.
FamilyTree
()
A
=
f
.
Person
(
"A"
,
69
,
True
)
A
=
c
.
Person
(
"A"
,
69
,
True
)
B
=
f
.
Person
(
"B"
,
69
,
True
)
B
=
c
.
Person
(
"B"
,
69
,
True
)
C
=
f
.
Person
(
"C"
,
69
,
False
)
C
=
c
.
Person
(
"C"
,
69
,
False
)
D
=
f
.
Person
(
"D"
,
69
,
True
)
D
=
c
.
Person
(
"D"
,
69
,
True
)
E
=
f
.
Person
(
"E"
,
666
,
False
)
E
=
c
.
Person
(
"E"
,
666
,
False
)
F
=
f
.
Person
(
"F"
,
420
,
False
)
ftree
.
insert_person
(
A
)
self
.
ftree
.
insert_person
(
A
)
ftree
.
insert_person
(
B
)
self
.
ftree
.
insert_person
(
B
)
ftree
.
insert_person
(
C
)
self
.
ftree
.
insert_person
(
C
)
ftree
.
insert_person
(
D
)
self
.
ftree
.
insert_person
(
D
)
ftree
.
insert_person
(
E
)
self
.
ftree
.
insert_person
(
E
)
self
.
ftree
.
insert_person
(
F
)
self
.
assertGreater
(
len
(
self
.
ftree
.
family_tree
),
0
)
B
.
set_parent
(
A
)
B
.
set_parent
(
A
)
C
.
set_parent
(
A
)
C
.
set_parent
(
A
)
D
.
set_parent
(
B
)
D
.
set_parent
(
B
)
E
.
set_parent
(
B
)
E
.
set_parent
(
B
)
ftree
.
find_root
()
F
.
set_parent
(
D
)
self
.
ftree
.
find_root
()
def
test_find_ancestors
(
self
):
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
):
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
):
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
):
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__"
:
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