[+] Finish Prep4
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
"""CSC111 Winter 2022 Prep 4: Programming Exercises
|
||||
|
||||
Instructions (READ THIS FIRST!)
|
||||
===============================
|
||||
|
||||
Your task in this prep is to implement each of the unimplemented Tree methods in this file.
|
||||
Use the recursive Tree method code template---decide whether to include the "size-one" base case
|
||||
by determining whether it would be redundant.
|
||||
|
||||
We have marked each place you need to write code with the word "TODO".
|
||||
As you complete your work in this file, delete each TODO comment.
|
||||
|
||||
You may add additional doctests, but they will not be graded. You should test your work
|
||||
carefully before submitting it!
|
||||
|
||||
Copyright and Usage Information
|
||||
===============================
|
||||
|
||||
This file is provided solely for the personal and private use of students
|
||||
taking CSC111 at the University of Toronto St. George campus. All forms of
|
||||
distribution of this code, whether as given or with any changes, are
|
||||
expressly prohibited. For more information on copyright for CSC111 materials,
|
||||
please consult our Course Syllabus.
|
||||
|
||||
This file is Copyright (c) 2022 Mario Badr, David Liu, and Diane Horton.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class Tree:
|
||||
"""A recursive tree data structure.
|
||||
|
||||
Note the relationship between this class and RecursiveList; the only major
|
||||
difference is that _rest has been replaced by _subtrees to handle multiple
|
||||
recursive sub-parts.
|
||||
|
||||
Representation Invariants:
|
||||
- self._root is not None or self._subtrees == []
|
||||
- all(not subtree.is_empty() for subtree in self._subtrees)
|
||||
"""
|
||||
# Private Instance Attributes:
|
||||
# - _root:
|
||||
# The item stored at this tree's root, or None if the tree is empty.
|
||||
# - _subtrees:
|
||||
# The list of subtrees of this tree. This attribute is empty when
|
||||
# self._root is None (representing an empty tree). However, this attribute
|
||||
# may be empty when self._root is not None, which represents a tree consisting
|
||||
# of just one item.
|
||||
_root: Optional[Any]
|
||||
_subtrees: list[Tree]
|
||||
|
||||
def __init__(self, root: Optional[Any], subtrees: list[Tree]) -> None:
|
||||
"""Initialize a new Tree with the given root value and subtrees.
|
||||
|
||||
If root is None, the tree is empty.
|
||||
|
||||
Preconditions:
|
||||
- root is not none or subtrees == []
|
||||
"""
|
||||
self._root = root
|
||||
self._subtrees = subtrees
|
||||
|
||||
def is_empty(self) -> bool:
|
||||
"""Return whether this tree is empty.
|
||||
|
||||
>>> t1 = Tree(None, [])
|
||||
>>> t1.is_empty()
|
||||
True
|
||||
>>> t2 = Tree(3, [])
|
||||
>>> t2.is_empty()
|
||||
False
|
||||
"""
|
||||
return self._root is None
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Return the number of items contained in this tree.
|
||||
|
||||
>>> t1 = Tree(None, [])
|
||||
>>> len(t1)
|
||||
0
|
||||
>>> t2 = Tree(3, [Tree(4, []), Tree(1, [])])
|
||||
>>> len(t2)
|
||||
3
|
||||
"""
|
||||
if self.is_empty():
|
||||
return 0
|
||||
else:
|
||||
size = 1 # count the root
|
||||
for subtree in self._subtrees:
|
||||
size += subtree.__len__() # could also write len(subtree)
|
||||
return size
|
||||
|
||||
############################################################################
|
||||
# Prep exercises start here
|
||||
############################################################################
|
||||
def num_negatives(self) -> int:
|
||||
"""Return the number of negative integers in this tree.
|
||||
|
||||
Preconditions:
|
||||
- all items in this tree are integers
|
||||
|
||||
Remember, 0 is *not* negative.
|
||||
|
||||
>>> t1 = Tree(17, [])
|
||||
>>> t1.num_negatives()
|
||||
0
|
||||
>>> t1 = Tree(-17, [])
|
||||
>>> t1.num_negatives()
|
||||
1
|
||||
>>> t1 = Tree(-17, [Tree(-1, [Tree(-20, [])]), Tree(-15, []), Tree(0, []), Tree(2, [Tree(-20, [])])])
|
||||
>>> t1.num_negatives()
|
||||
5
|
||||
"""
|
||||
if self.is_empty():
|
||||
return 0
|
||||
elif not self._subtrees:
|
||||
return int(self._root < 0)
|
||||
else:
|
||||
return int(self._root < 0) + sum(s.num_negatives() for s in self._subtrees)
|
||||
|
||||
def maximum(self: Tree) -> int:
|
||||
"""Return the maximum value stored in this tree.
|
||||
|
||||
Return 0 if this tree is empty.
|
||||
|
||||
Preconditions:
|
||||
- all values in this tree are positive integers.
|
||||
|
||||
>>> t1 = Tree(17, [])
|
||||
>>> t1.maximum()
|
||||
17
|
||||
>>> t1 = Tree(17, [Tree(18, []), Tree(2, [Tree(19, [])])])
|
||||
>>> t1.maximum()
|
||||
19
|
||||
"""
|
||||
if self.is_empty():
|
||||
return 0
|
||||
elif not self._subtrees:
|
||||
return int(self._root)
|
||||
else:
|
||||
return max(s.maximum() for s in self._subtrees)
|
||||
|
||||
def height(self: Tree) -> int:
|
||||
"""Return the height of this tree.
|
||||
|
||||
Please refer to the prep readings for the definition of tree height.
|
||||
|
||||
>>> t1 = Tree(17, [])
|
||||
>>> t1.height()
|
||||
1
|
||||
>>> t1 = Tree(17, [Tree(18, []), Tree(2, [Tree(19, [])])])
|
||||
>>> t1.height()
|
||||
3
|
||||
"""
|
||||
if self.is_empty():
|
||||
return 1
|
||||
elif not self._subtrees:
|
||||
return 1
|
||||
else:
|
||||
return 1 + max(s.height() for s in self._subtrees)
|
||||
|
||||
def __contains__(self, item: Any) -> bool:
|
||||
"""Return whether this tree contains <item>.
|
||||
|
||||
>>> t = Tree(1, [])
|
||||
>>> t.__contains__(-30) # Could also write -30 in t
|
||||
False
|
||||
>>> t.__contains__(1)
|
||||
True
|
||||
>>> t = Tree(17, [Tree(18, []), Tree(2, [Tree(19, [Tree('A', [])])])])
|
||||
>>> 19 in t
|
||||
True
|
||||
>>> 2 in t
|
||||
True
|
||||
>>> 3 in t
|
||||
False
|
||||
>>> 'A' in t
|
||||
True
|
||||
"""
|
||||
if self.is_empty():
|
||||
return False
|
||||
elif not self._subtrees:
|
||||
return self._root == item
|
||||
else:
|
||||
return self._root == item or any(item in s for s in self._subtrees)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import python_ta.contracts
|
||||
python_ta.contracts.check_all_contracts()
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
import python_ta
|
||||
python_ta.check_all(config={
|
||||
'max-line-length': 100,
|
||||
'disable': ['E1136']
|
||||
})
|
||||
Reference in New Issue
Block a user