# Name: Alyssa P. Hacker # Kerbers: aph # homework_3_sol.py ##### Solution for Homework 3, exercises 6.1 - 7.2 ###### # ********** Exercise 6.1 ********** ## Example Bugs ## ## 1. b is not assigned to a value [fix by giving b a value] ## 2. large_num doesn't return anything [fix by changing res = to return] ## 3. The line big = large_num(b) will give big the value of None [fix in the previous step] ## 4. negate(b) has not been assigned to neg_b [fix by doing so] ## 5. num is local to negate and local to large_num, but it's not global, ## so it cannot be used globally (in the line neg_b = num) [fix by assigning neg_b = negate(b) ## instead of neg_b = num] # ********** Exercise 6.2 ********** ## MUTABLE: Elements may be changed: lists, dictionaries. ## IMMUTABLE: Elements may NOT be changed: strings, tuples. # ********** Exercise 6.3 ********** def ball_collide(ball1, ball2): ''' Computes whether or not two balls are colliding ball1: a tuple of (x-coord, y-coord, radius) nums (ints or floats); represents first ball ball2: a tuple of (x-coord, y-coord, radius) nums (ints or floats); represents second ball returns: True if the balls collide and False if they do not collide ''' # unpack tuples (x1, y1, r1) = ball1 (x2, y2, r2) = ball2 # use the distance formula from algebra... if (float(x1) - x2)**2 + (float(y1) - y2)**2 <= (float(r1) + r2)**2: return True else: return False # ball1 and ball2 must be tuples (x, y, z, r) def ball_collide_3D(ball1, ball2): # unpack tuples (x1, y1, z1, r1) = ball1 (x2, y2, z2, r2) = ball2 # more algebra yay! if (float(x1) - x2)**2 + (float(y1) - y2)**2 \ + (float(z1) - z2)**2 <= (float(r1) + r2)**2: return True else: return False # Test Cases for Exercise 6.3 print ball_collide((0, 0, 1), (3, 3, 1)) # Should be False print ball_collide((5, 5, 2), (2, 8, 3)) # Should be True print ball_collide((7, 8, 2), (4, 4, 3)) # Should be True print ball_collide_3D((0, 0, 0, 1), (3, 3, 3, 1)) # Should be False print ball_collide_3D((5, 5, 1, 2), (2, 8, 7, 3)) # Should be False print ball_collide_3D((5, 5, 1, 2), (2, 8, 1, 3)) # Should be True # ********** Exercise 7.1 ********** def add_class(class_num, desc, class_dict): ''' Adds a class number/class name pair to a dictionary class_num: a string; the MIT number associated with the class desc: a string; the English name of the class class_dict: a dictionary with the keys being class numbers and the values being class names returns: nothing; only modifies class_dict ''' class_dict[class_num] = desc def print_classes(course, class_dict): ''' Prints out all the classes you've taken in a given Course. If no classes were taken in the Course, print out that none were taken course: a string; the Course for which we would like to print out classes taken class_dict: a dictionary with the keys being class numbers and the values being class names returns: nothing; simply prints out relevant information ''' # tracks whether or not we've printed printed = False # created list of keys my_classes_keys = class_dict.keys() # examines list of keys by iterating through the generated key list for class_key in my_classes_keys: # we look at the key, from the start through the '.', and compare # this to the requested course if class_key[:class_key.index('.')] == course: print class_key, '-', class_dict[class_key] # if we get here, we took at least 1 class in this course, # so we change printed to True printed = True # Finally, if we never printed a course out, we must not have taken # a class in that course if not printed: print 'No Course ' + course + ' classes taken.' # Test Cases for Exercise 7.1 my_classes = {'1.070J / 12.320J' : 'Introduction to Hydrology', '6.004' : 'Computation Structures', '7.012' : 'Introductory Biology', '8.033' : 'Relativity', '18.310' : 'Principles of Applied Mathematics', 'HAA.7123' : 'Latin BAM'} add_class('6.S189', 'Introduction to Python', my_classes) add_class('18.410J', 'Advanced Algorithms', my_classes) add_class('6.824', 'Distributed Computer Systems Engineering', my_classes) print_classes('6', my_classes) # prints '6.004', '6.189', 6.824' print_classes('1', my_classes) # prints '1.070J / 12.320J' but not course '18' classes print_classes('18', my_classes) # prints '18.310' and '18.410J' but not '1.070' print_classes('3', my_classes) # print 'No Course 3 classes taken.' # ********** Exercise 7.2 ********** def buildAddrBook(fileName): ''' Builds an address book from a file. fileName: a string, the name of the file to read in File must be in the format specified in Exercise 5.5. returns: a dictionary with keys and values generated from the file, as specified in Exercise 5.5. ''' # create empty dictionary to use as our address book addrBook = {} # open file inputF = open(fileName) # loop through each line of the file for line in inputF: # split the line separated by commas splitted_line = line.split(',') # 0th and 1st index corresponds to LastName, FirstName name = splitted_line[0] + ', ' + splitted_line[1] # 2nd index is phone number phone = splitted_line[2] # all the rest are email addresses # do rstrip to remove possible newline character in the email email = [x.rstrip("\r\n") for x in splitted_line[3:]] # combine phone and email to be value of the key name addrBook[name] = [phone] + email # close the file when we're done! inputF.close() return addrBook def changeEntry(addrBook, entry, field, newValue): ''' Changes one entry in the specified address book. addrBook: a dictionary in the address book format returned by buildAddrBook. entry: a string; the pre-existing entry to change field: a string; the field to change (one of: "name", "phoneNumber", "emailAddress") newValue: the new value for the specified field returns: nothing; only modifies addrBook ''' # get all keys from addrBook addrBook_keys = addrBook.keys() # check if entry valid if not entry in addrBook_keys: print 'Invalid entry:', entry elif field == 'name': # get value from current key value = addrBook[entry] # delete key:value pair del addrBook[entry] # store value in new key newValue addrBook[newValue] = value elif field == 'phoneNumber': # change 0th index of addrBook[entry] # with new value; recall that the phoneNumber # is always on the 0th index of the value addrBook[entry][0] = newValue elif field == 'emailAddress': # append newValue to the value of addrBook[entry] addrBook[entry].append(newValue) # invalid field else: print 'Unexpected field:', field # Test cases for Exercise 7.2 # let's build the address book using our function above addrBook = buildAddrBook('rawAddresses.csv') changeEntry(addrBook, 'Lemon, Liz', 'emailAddress', 'lizzing@starwars.net') print addrBook['Lemon, Liz'] == \ ['(202) 555-8130', 'lizlemon@nbc.com', 'lizzing@starwars.net'] # should print True changeEntry(addrBook, 'Lemon, Liz', 'phoneNumber', '1-900-OKFACE') print addrBook['Lemon, Liz'] == \ ['1-900-OKFACE', 'lizlemon@nbc.com', 'lizzing@starwars.net'] # should print True changeEntry(addrBook, 'Lemon, Liz', 'name', 'Lemon, Elizabeth') print addrBook['Lemon, Elizabeth'] == \ ['1-900-OKFACE', 'lizlemon@nbc.com', 'lizzing@starwars.net'] # should print True # printing addrBook['Lemon, Liz'] will throw a KeyError # so we catch it and display an error msg try: print addrBook['Lemon, Liz'] except KeyError: print '\'Lemon, Liz\' does not exist in the dictionary.' # should print 'Invalid entry: Bitdiddle, Ben' changeEntry(addrBook, 'Bitddiddle, Ben', 'emailAddress', 'bitddiddly@bu.edu') # should print 'Unexpected field: homeAddress' changeEntry(addrBook, 'Beaver, Tim', 'homeAddress', 'Baltimore, MD')