# CMU 15-112 Fall 2018: Fundamentals of Programming and Computer Science Homework 9 (Due Sunday 28-Oct, at 5pm)

• Due to the tragedy that occurred on Saturday, we are extending the homework deadline to Monday 5pm. Office hours on Saturday will be remote (via Piazza). Please take care of yourself and contact CAPS if you need to talk to someone.

• Reminder: all problems that are not explicitly marked COLLABORATIVE must be completed individually, as stated in the course syllabus.
• Note: some problems on this assignment are labeled as 'recursive'. For these problems, using a for loop, a while loop, a list/set/dictionary comprehension, or a generator will result in the code failing on Autolab. You also may not use inherently iterative functions. These include range, sum, max, min, reversed, sorted, list.count, list.sort, list.reverse, str.replace, and str.join.

• To start:
1. Create a folder named 'week9'
2. Create a new file hw9.py in that folder.
3. Edit hw9.py using Pyzo
4. When you are ready, submit hw9.py to Autolab. For this hw, you may submit up to 5 times, but only your last submission counts.
• Do not hardcode the test cases in your solutions.
• Note: you are not required to generate additional test cases for VendingMachine, the Bird classes, or the Equation classes.

COLLABORATIVE PROBLEMS

1. COLLABORATIVE Code-Writing: Vending Machine Class [15pts]
Write the VendingMachine class so that it passes testVendingMachineClass, and uses the OOP constructs we learned this week as appropriate.

Hint: Make sure you're representing money properly wherever it might appear in the string representation of a Vending Machine. The test cases shown here don't cover every possible case...

def testVendingMachineClass(): print("Testing Vending Machine class...", end="") # Vending machines have three main properties: # how many bottles they contain, the price of a bottle, and # how much money has been paid. A new vending machine starts with no # money paid. vm1 = VendingMachine(100, 125) assert(str(vm1) == "Vending Machine:<100 bottles; \$1.25 each; \$0 paid>") assert(vm1.isEmpty() == False) assert(vm1.getBottleCount() == 100) assert(vm1.stillOwe() == 125) # When the user inserts money, the machine returns a message about their # status and any change they need as a tuple. assert(vm1.insertMoney(20) == ("Still owe \$1.05", 0)) assert(str(vm1) == "Vending Machine:<100 bottles; \$1.25 each; \$0.20 paid>") assert(vm1.stillOwe() == 105) assert(vm1.getBottleCount() == 100) assert(vm1.insertMoney(5) == ("Still owe \$1", 0)) # When the user has paid enough money, they get a bottle and # the money owed resets. assert(vm1.insertMoney(100) == ("Got a bottle!", 0)) assert(vm1.getBottleCount() == 99) assert(vm1.stillOwe() == 125) assert(str(vm1) == "Vending Machine:<99 bottles; \$1.25 each; \$0 paid>") # If the user pays too much money, they get their change back with the # bottle. assert(vm1.insertMoney(500) == ("Got a bottle!", 375)) assert(vm1.getBottleCount() == 98) assert(vm1.stillOwe() == 125) # Machines can become empty vm2 = VendingMachine(1, 120) assert(str(vm2) == "Vending Machine:<1 bottle; \$1.20 each; \$0 paid>") assert(vm2.isEmpty() == False) assert(vm2.insertMoney(120) == ("Got a bottle!", 0)) assert(vm2.getBottleCount() == 0) assert(vm2.isEmpty() == True) # Once a machine is empty, it should not accept money until it is restocked. assert(str(vm2) == "Vending Machine:<0 bottles; \$1.20 each; \$0 paid>") assert(vm2.insertMoney(25) == ("Machine is empty", 25)) assert(vm2.insertMoney(120) == ("Machine is empty", 120)) assert(vm2.stillOwe() == 120) vm2.stockMachine(20) # Does not return anything assert(vm2.getBottleCount() == 20) assert(vm2.isEmpty() == False) assert(str(vm2) == "Vending Machine:<20 bottles; \$1.20 each; \$0 paid>") assert(vm2.insertMoney(25) == ("Still owe \$0.95", 0)) assert(vm2.stillOwe() == 95) vm2.stockMachine(20) assert(vm2.getBottleCount() == 40) # We should be able to test machines for basic functionality vm3 = VendingMachine(50, 100) vm4 = VendingMachine(50, 100) vm5 = VendingMachine(20, 100) vm6 = VendingMachine(50, 200) vm7 = "Vending Machine" assert(vm3 == vm4) assert(vm3 != vm5) assert(vm3 != vm6) assert(vm3 != vm7) # should not crash! s = set() assert(vm3 not in s) s.add(vm4) assert(vm3 in s) s.remove(vm4) assert(vm3 not in s) assert(vm4.insertMoney(50) == ("Still owe \$0.50", 0)) assert(vm3 != vm4) print("Done!")

2. COLLABORATIVE Code Writing: Bird Class and Subclasses [15pts]
Write the Bird, Penguin, and MessengerBird classes so that they pass testBirdClasses and use the OOP constructs we learned this week as appropriate.

def getLocalMethods(clss): import types # This is a helper function for the test function below. # It returns a sorted list of the names of the methods # defined in a class. It's okay if you don't fully understand it! result = [ ] for var in clss.__dict__: val = clss.__dict__[var] if (isinstance(val, types.FunctionType)): result.append(var) return sorted(result) def testBirdClasses(): print("Testing Bird classes...", end="") # A basic Bird has a species name, can fly, and can lay eggs bird1 = Bird("Parrot") assert(type(bird1) == Bird) assert(isinstance(bird1, Bird)) assert(bird1.fly() == "I can fly!") assert(bird1.countEggs() == 0) assert(str(bird1) == "Parrot has 0 eggs") bird1.layEgg() assert(bird1.countEggs() == 1) assert(str(bird1) == "Parrot has 1 egg") bird1.layEgg() assert(bird1.countEggs() == 2) assert(str(bird1) == "Parrot has 2 eggs") assert(getLocalMethods(Bird) == ['__init__', '__repr__', 'countEggs', 'fly', 'layEgg']) # A Penguin is a Bird that cannot fly, but can swim bird2 = Penguin("Emperor Penguin") assert(type(bird2) == Penguin) assert(isinstance(bird2, Penguin)) assert(isinstance(bird2, Bird)) assert(bird2.fly() == "No flying for me.") assert(bird2.swim() == "I can swim!") bird2.layEgg() assert(bird2.countEggs() == 1) assert(str(bird2) == "Emperor Penguin has 1 egg") assert(getLocalMethods(Penguin) == ['fly', 'swim']) # A MessengerBird is a Bird that can optionally carry a message bird3 = MessengerBird("War Pigeon", message="Top-Secret Message!") assert(type(bird3) == MessengerBird) assert(isinstance(bird3, MessengerBird)) assert(isinstance(bird3, Bird)) assert(not isinstance(bird3, Penguin)) assert(bird3.deliverMessage() == "Top-Secret Message!") assert(str(bird3) == "War Pigeon has 0 eggs") assert(bird3.fly() == "I can fly!") bird4 = MessengerBird("Homing Pigeon") assert(bird4.deliverMessage() == "") bird4.layEgg() assert(bird4.countEggs() == 1) assert(getLocalMethods(MessengerBird) == ['__init__', 'deliverMessage']) print("Done!")

3. COLLABORATIVE Code Writing: recursive alternatingSum(lst) [10pts]
Write the function alternatingSum(lst) that takes a possibly-empty list of numbers, lst, and returns the alternating sum of the list, where every other value is subtracted rather than added. For example: alternatingSum([1,2,3,4,5]) returns 1-2+3-4+5 (that is, 3). If lst is empty, return 0.

4. COLLABORATIVE Code Writing: recursive generateCharacterString [15pts]
Write the function generateCharacterString(s) that takes a two-character string and returns a new string that contains the all of the characters (in ascii order) between the first character and the second character. For example, generateCharacterString("ko") would return "klmno". This should also work backwards, so generateCharacterString("ME") would return "MLKJIHGFE". If the initial provided string is not two characters long, return the empty string; if the provided string contains two identical characters (for example, "22"), return that character ("2").

5. SOLO PROBLEMS

6. Short Answer: Design a Sports Class [10pts]
When programming, you will not always be given the class structure, properties, and methods that you need to implement; sometimes, you need to figure out an appropriate structure yourself. In this task, you will be designing class inheritance structures, methods, and properties for a specific context.

For the context, you may choose any team sport that is interesting to you. Common examples include soccer, baseball, football, hockey, basketball, rugby, cricket, ultimate, quidditch, and more! Assume you want to define a Player class for that sport. You must describe at least two methods and two properties that would be held by the Player class, two subclasses of Player, and whether these subclasses would need to override or inherit the methods defined for the Player class. All of this should be done in a top-level comment in your submitted file, in the following format:

""" #5 Sports Class Answer Sport: ___ Player Class properties: ___ Player Class methods: ___ Player Class Subclass one: ___ Methods to override: ___ Methods to inherit: ___ Player Class Subclass two: ___ Methods to override: ___ Methods to inherit: ___ """

All properties and methods should be clearly named so that someone else would immediately understand their purpose and see its relevance to the class. If needed, feel free to add comments further explaining the purpose of a method or property. Get creative, and have fun!

7. Code Writing: Equation Classes [20pts]
Write the Polynomial and Quadratic classes so that they pass testEquationClasses and use the OOP constructs we learned this week as appropriate.