Introduction to Computer Science II

Homework and Lab 4

Due by 3:10pm on Tuesday, February 3

Reading

Read chapter 8 and the week 4 lecture notes.

Lab

Monday 1:30pm-3:00 in room 512 in 14 E Jackson or via Zoom.

Problems

Solve the following by implementing the corresponding functions in homework4.py. When done, submit that file through D2L.


1.    Implement class SavingsAccount as a subclass of the class BankAccount you developed in Homework 2. Your implementation should override the inherited construct method __init__() and add an additional method addInterest() using the following specs:
Usage:
>>> s = SavingsAccount(3, 100)
>>> s.balance()
100
>>> s.addInterest()
>>> s.balance()
103.0
>>> s = SavingsAccount(3)
>>> s.deposit(1000)
>>> s.addInterest()
>>> s.balance()
1030.0


2.    There are some problems with the implementation of the class BankAccount from Homework 2, and they are illustrated here:
>>> x = BankAccount(-700)
>>> x.balance()
-700
>>> x.withdraw(70)
>>> x.balance()
-770
>>> x.deposit(-7)
>>> x.balance()
Balance: -777
The problems are: (1) a bank account with a negative balance can be created, (2) the withdrawal amount is greater than the balance, and (3) the deposit amount is negative. Modify the code for the BankAccount class so that a ValueError exception is thrown for any of these violations, together with an appropriate message: 'Illegal balance', 'Overdraft', or 'Negative deposit'. For example:
Usage:
>>> x = BankAccount2(-700)
Traceback (most recent call last):
...
ValueError: Negative balance
>>> x = BankAccount2(700)
>>> x.withdraw(800)
Traceback (most recent call last):
...
ValueError: Overdraft
>>> x.deposit(-100)
Traceback (most recent call last):
...
ValueError: Negative deposit



3.    In problem 2, a generic ValueError exception is raised if any of the three violations occur. It would be more useful if a more specific, user-defined exception is raised instead. Define new exception classes NegativeBalanceError, OverdraftError, and DepositError that would be raised instead. In addition, the informal string representation of the exception object should contain the balance that would result from the negative balance account creation, the overdraft, or the negative deposit. For example, when trying to create a bank account with a negative balance, the error message should include the balance that would result if the bank account creation was allowed:
>>> x = BankAccount3(-5)
Traceback (most recent call last):
...
NegativeBalanceError: Account created with negative balance -5
When a withdrawal results in a negative balance, the error message should also include the balance that would result if the withdrawal was allowed:
>>> x = BankAccount3(5)
>>> x.withdraw(7)
Traceback (most recent call last):
...
OverdraftError: Operation would result in negative balance -2
If a negative deposit is attempted, the negative deposit amount should be included in the error message:
>>> x.deposit(-3)
Traceback (most recent call last):
...
DepositError: Negative deposit -3
Finally, reimplement the class BankAccount to use these new exception classes instead of ValueError.



4.    Implement a class myInt that behaves almost the same as the built-in class int, except when trying to add an object of type myInt. Then, this strange behavior occurs:
Usage:
>>> x = myInt(5)
>>> x * 4
20
>>> x * (4 + 6)
50
>>> x + 6
'Whatever ... '


5.
    Develop a class myList that is a subclass of the built-in list class. The only dierence between myList and list is that the sort method is overridden. myList containers should behave just like regular lists, except as shown next:
Usage:
>>> x = myList([1, 2, 3])
>>> x
[1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1]
>>>
x[2]
1
>>> x.sort()
You wish...



6.    Consider the class tree hierarchy:

Implement six classes to model this taxonomy with Python inheritance. In class Animal, implement method speak() that will be inherited by the descendant classes of Animal. In method Mammal, implement method drink() that will be inherited by the descendents classes of Mammal. Complete the implementation of the six classes so that they exhibit this behavior:
Usage:
>>> tweety = Animal()
>>> tweety.speak()

>>> tweety.drink()
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    tweety.drink()
AttributeError: 'Animal' object has no attribute 'drink'
>>> snoopy = Dog()
>>> garfield = Cat()
>>> snoopy.speak()
Wooof!
>>> garfield.speak()
Meeow!
>>> snoopy.drink()
Drinking milk...
>>> dude = Hacker()
>>> dude.speak()
Hello World!
>>> kingkong = Primate()
>>> kingkong.speak()
Boooh


7.    [Lab exercise] Implement a container class called PriorityQueue. The class should support methods:
In addition to these methods your class should support the overloaded operator len() as shown below.
Usage:
>>> pq = PriorityQueue()
>>> pq.insert(3)
>>> pq.insert(1)
>>> pq.insert(5)
>>> pq.insert(2)
>>> pq.min()
1
>>> pq.removeMin()
>>> pq.min() 2
>>> len(pq)
3
>>> pq.isEmpty()
False
Note: Think about the class invariant. Under the hood, there will be some type of list to store the numbers in the priority queue. Consider two possibilities: 1) the list is unsorted and 2) the list is unsorted. How does your implementation change between the two class invariants?