CSC 243: PYTHON FOR PROGRAMMERS Professor: Amber Settle FINAL EXAM NOVEMBER 23, 2020 The exam is out of 100 points and the points for each question are listed next to the problem. You should begin by...

CSC 243: PYTHON FOR PROGRAMMERS Professor: Amber Settle FINAL EXAM NOVEMBER 23, 2020 The exam is out of 100 points and the points for each question are listed next to the problem. You should begin by downloading the file csc243final.py from the zip file on the D2L site under the Exams section in the Content area. Write all of your answers into the file and upload the file when you have completed the final exam. You have until 8 pm for the final exam. All submissions must be completed by that time in order to be considered. No late submissions will be considered for any reason. The exam is open book and open notes. You are allowed to use the IDLE editor and the Python shell (or the IDE or your choice) during the exam. You are not allowed to use any online resources during the exam, including the Python tutor visualization tool. You are not allowed to talk to, share files with, collaborate with, exchange email with, text, or in any other way communicate with someone other than Dr. Settle during the exam. If you have questions during the exam, you may send Dr. Settle an email. The emails will be answered in the order in which they are received. Dr. Settle may opt to not answer questions about the exam if answering the question is supposed to be part of your task on the exam. Please be aware that the sample executions and/or test cases are only examples. You may not make any assumptions about the information that the functions will receive beyond what is specified in the problem description. Your functions must work correctly on all valid inputs and parameters. Please note that you may not find all problems equally easy. If you get stuck on a problem, move on to the next one. 2 QUESTION 1: (25 POINTS) Write a recursive function onlyPosFloat() that takes an arbitrarily nested list as a parameter and returns True if all of the items in the list are positive, floating point numbers and False if there are any elements in the list that are not floating point values or if there are any floating point values in the list that are zero or negative. If the list is empty, the function returns True. Note that your function must be recursive. You are not allowed to use any list methods in your function other than indexing (e.g. lst[i] for some integer i), slicing (e.g. lst[i:j] for some non-negative integers i and j), and len(). You are encouraged to use the type() function and the logical operators and and or. In writing the function you cannot use any loops or global variables, change the number of parameters of the function, provide any initial values to the parameters, or define any helper functions. The first value given to the function should and will be a list. You should also only make recursive calls on lists. The function should not alter the list passed as a parameter in any way. The function must return a Boolean (e.g. True or False) for all possible parameters. Boolean values should not be treated as numbers in your function. The following shows the behavior of the function on some sample parameters. Please remember that these examples are just that. Your function must work correctly on all valid parameters, and you may not make any assumptions about the number of nested sublists or the number of or placement of items in the parameter list. >>> ans = onlyPosFloat([]) >>> ans True >>> lst = [1.1, [2.2, [3.3, 4.4]], 5.5] >>> ans = onlyPosFloat(lst) >>> ans True >>> lst [1.1, [2.2, [3.3, 4.4]], 5.5] >>> ans = onlyPosFloat([[[1.1]], [2.2, [3.3, [[4.4]]]], [[5.5]]]) >>> ans True >>> ans = onlyPosFloat([-1.1, [2.2, [3.3, [[4.4]]]], [[5.5]]]) >>> ans False >>> ans = onlyPosFloat([1.1, [2.2, [3.3, [[-4.4]]]], [[5.5]]]) >>> ans False >>> ans = onlyPosFloat([1, [2.2, [3.3, [[4.4]]]], [[5.5]]]) >>> ans False >>> ans = onlyPosFloat([1.1, [2.2, [3.3, [[4.4]]]], [[0.0]]]) >>> ans False >>> onlyPosFloat([[[1.1]], [2.2, [3.3, [[4.4]]]], [['test']]]) False >>> onlyPosFloat([True, [2.2, [3.3, [[4.4]]]], [[5.5]]]) False >>> 3 QUESTION 2: (25 POINTS) Write a recursive function getTxtList() that takes a string representing a name of a directory and a string s representing a desired piece of text as parameters and returns a list of all the text files containing at least one occurrence of the string s within it. A text file is a file with a name that ends with the extension .txt (in any possible capitalization). Only text files should be considered. Any other file type should be ignored. Note that the files must contain the string s inside of their contents, not in their name. The string s may appear in any capitalization inside the file. Please note that your function must be recursive and that it must work as described on any directory structure, not just the ones provided as examples. You cannot make any assumptions about the locations of files in the directory structure, the types of files in the directory structure, or the depth of the directory structure. You may not change the number of parameters of the function, provide default values to the parameters, define any helper functions, or use any global variables, and the function must return and not print the text files containing s. It is expected that a correct recursive solution to the problem will contain at least one loop, although the majority of the work will be done via recursion. Your code must work on any operating system. For full credit, close any files you open. Below is also a display of the items found in the sample directory included in the exam zip file. For your convenience a zip file with the files found in the directories is provided separately in a file called files.zip. That will allow you to examine the contents of the files without having to find them inside the directory structure: test\doc.pdf test\FILE2.TXT test\prog2.py test\test1 test\test1\file3.txt test\test2 test\test2\file3.txt test\test2\test2a test\test2\test2a\file1.txt test\test2\test2a\FILE2.TXT test\test2\test2a\file3.txt test\test2\test2b test\test2\test2b\doc.pdf test\test2\test2b\prog1.py test\test3 test\test3\prog1.py test\test4 test\test4\file1.txt test\test4\test4a test\test4\test4a\FILE2.TXT test\test4\test4a\prog1.py test\test4\test4a\test4aa test\test4\test4a\test4aa\file1.txt test\test4\test4a\test4aa\prog1.py test\test4\test4b test\test4\test4b\FILE2.TXT test\test4\test4b\file3.txt test\test4\test4b\prog1.py test\test4\test4c test\test4\test4c\doc.pdf test\test4\test4c\prog2.py 4 The next page shows several sample executions of the function on the sample directory above as well as an empty directory. You will have to create the empty directory yourself since I cannot include it in the zip file I upload to D2L: >>> lst = getTxtList('test', 'LaRue') >>> lst ['test\\FILE2.TXT', 'test\\test2\\test2a\\file1.txt', 'test\\test2\\test2a\\FILE2.TXT', 'test\\test4\\file1.txt', 'test\\test4\\test4a\\FILE2.TXT', 'test\\test4\\test4a\\test4aa\\file1.txt', 'test\\test4\\test4b\\FILE2.TXT'] >>> len(lst) 7 >>> lst = getTxtList('test', 'JOJO') >>> lst ['test\\test1\\file3.txt', 'test\\test2\\file3.txt', 'test\\test2\\test2a\\file1.txt', 'test\\test2\\test2a\\file3.txt', 'test\\test4\\file1.txt', 'test\\test4\\test4a\\test4aa\\file1.txt', 'test\\test4\\test4b\\file3.txt'] >>> len(lst) 7 >>> lst = getTxtList('test', 'tabby') >>> lst ['test\\FILE2.TXT', 'test\\test2\\test2a\\FILE2.TXT', 'test\\test4\\test4a\\FILE2.TXT', 'test\\test4\\test4b\\FILE2.TXT'] >>> len(lst) 4 >>> lst = getTxtList('test', 'HUMAN') >>> lst ['test\\test2\\test2a\\file1.txt', 'test\\test4\\file1.txt', 'test\\test4\\test4a\\test4aa\\file1.txt'] >>> len(lst) 3 >>> lst = getTxtList('test', 'Amber') >>> lst [] >>> lst = getTxtList('empty', 'LaRue') >>> lst [] >>> 5 QUESTION 3: (30 POINTS) The GroceryList class contains information about items on a grocery list. It holds the information in a dictionary. Each key in the dictionary is the name of an item (e.g., a string), and each value in the dictionary is an integer representing the number of the item that should be purchased. The value of each item must be strictly greater than 0 and an integer. The constructor and __repr__ method for the class are defined for you in the template. The constructor initializes a variable in the object to an empty dictionary and creates a variable to hold the minimum quantity for any item. The __repr__ method simply returns the internal dictionary as an augmented string. You can find the incomplete class in the template for the exam. You will complete the class by writing the following methods: 1. (5 points) validatePair: The method takes two parameters (beyond the self object) item and val. It returns True if item is a string, val is an integer, and val is greater than or equal to the minimum quantity required for items. It returns False if any of the previous conditions are not met. For full credit the method must use the variable stored in the object by the constructor that holds the minimum quantity. 2. (8 points) addItem: The method takes two parameters (beyond the self object), one representing the name of an item and the second representing the quantity of that item. The method calls validatePair to validate its parameters. If validatePair returns False then the function does not change the internal dictionary and returns False. If validatePair returns True and the item is not already in the dictionary, the function stores the new item in the dictionary in all lowercase with the associated quantity as its value and returns True. If the item is already in the dictionary, the function does not modify the dictionary and returns False. The function must call validatePair. Solutions that duplicate code found in validatePair will not earn full credit. 3. (9 points) updateItem: The method takes two parameters (beyond the self object), one representing the name of an item and the second representing the quantity of that item. The method calls validatePair to validate its parameters. If validatePair returns False then the function does not change the internal dictionary and returns False. If validatePair returns True, the function checks if the item is already in the dictionary (in lowercase). If it is, it updates the dictionary with the new value and returns True. If the item is not in the dictionary, it does not change the dictionary and returns False. The function must call validatePair. Solutions that duplicate code found in validatePair will not earn full credit. 4. (8 points) removeItem: The method takes a single parameter (beyond the self object) that represents the name of an item. If the parameter is a string and in the dictionary (in lowercase) it deletes the key-value pair associated with the string from the dictionary and returns True. Otherwise it does not modify the dictionary and returns False. Below and on the following pages you can see sample runs using the completed class. Please be aware that these are just examples, and your class must be written as described above. >>> g1 = GroceryList() >>> g1 GroceryList({}) >>> ans = g1.addItem('ONIONS', 3) 6 >>> ans True >>> g1 GroceryList({'onions': 3}) >>> ans = g1.addItem('mILk', 0) >>> ans False >>> g1 GroceryList({'onions': 3}) >>> ans = g1.addItem('carrots', 3.5) >>> ans False >>> g1 GroceryList({'onions': 3}) >>> ans = g1.addItem('BREAD', 1) >>> ans True >>> g1 GroceryList({'onions': 3, 'bread': 1}) >>> ans = g1.addItem(52, 'one') >>> ans False >>> g1 GroceryList({'onions': 3, 'bread': 1}) >>> ans = g1.updateItem('onions', 4) >>> ans True >>> g1 GroceryList({'onions': 4, 'bread': 1}) >>> ans = g1.updateItem('carrots', 3) >>> ans False >>> g1 GroceryList({'onions': 4, 'bread': 1}) >>> ans = g1.updateItem('bread', 0) >>> ans False >>> g1 GroceryList({'onions': 4, 'bread': 1}) >>> ans = g1.updateItem('bread', 0.5) >>> ans False >>> g1 GroceryList({'onions': 4, 'bread': 1}) >>> ans = g1.removeItem('BREAD') >>> ans True >>> g1 GroceryList({'onions': 4}) >>> ans = g1.removeItem('carrots') >>> ans False >>> g1 GroceryList({'onions': 4}) >>> ans = g1.removeItem(7) >>> ans 7 False >>> g1 GroceryList({'onions': 4}) >>> g2 = GroceryList() >>> g2 GroceryList({}) >>> ans = g2.addItem('carrots', 10) >>> ans True >>> g2 GroceryList({'carrots': 10}) >>> ans = g2.addItem('CARROTS', 5) >>> ans False >>> g2 GroceryList({'carrots': 10}) >>> ans = g2.updateItem('CARROTS', 5) >>> ans True >>> g2 GroceryList({'carrots': 5}) >>> ans = g2.validatePair('soup', 5) >>> ans True >>> ans = g2.validatePair('soup', 5.5) >>> ans False >>> ans = g2.validatePair('soup', 'one') >>> ans False >>> ans = g2.validatePair(5.5, 5) >>> ans False >>> ans = g2.validatePair('soup', 0) >>> ans False >>> 8 QUESTION 4: (20 POINTS) Write a class JPGLinkDescript that is a subclass of the HTMLParser class. It builds a list of all the descriptions associated with links to JPG images found in an HTML page. A link to a JPG image is an anchor tag that has as its hypertext reference a file that ends with .jpg (in any possible capitalization). For example, the following is a link to a JPG image: Djengo the cat If the parser encountered that link, it would gather the description: "Djengo the cat" into the list it builds since that string is the one found in between the opening and closing anchor tags that contain a hypertext reference to a JPG image. If the parser encountered the following link: Read a quote then it would not gather any information since that link is not for a JPG image. Similarly if the page encountered a link like this:
Read the news
it would also not gather any information since that link is connected to a web page rather than an image. Links to email addresses or to relative HTML pages should also be ignored. Three methods of the class have already been written for you: the constructor, handle_endtag, and getList. These are found in the exam template and should not be changed. To implement JPGLinkDescript you will need to write two methods: 1. handle_starttag: The method checks if the tag that resulted in the function being called is an anchor tag. If it is and the value associated with the href attribute is a JPG image (in any possible capitalization), the method sets the Boolean variable initialized in the constructor to indicate that a JPG image tag is live. The Boolean variable is unset in the handle_endtag method, which is already written for you. 2. handle_data: If the Boolean variable used for communication has been set to indicate that a JPG image tag is live, the method puts its data into the list the parser is building. You should remove leading and trailing whitespace from the data before putting it into the list. You can find the template for the class and a test function testParser() in the final exam template file. The following shows what the test function would display on several sample web 9 pages. You should look at the HTML for the test files to see what is being accumulated and what is being ignored by the parser: >> lst = testParser('http://facweb.cdm.depaul.edu/asettle/csc243/web/fEOne.html') >>> lst ['Cookie the Cat', 'And a herd of elephants for good measure'] >>> lst = testParser('http://facweb.cdm.depaul.edu/asettle/csc243/web/fETwo.html') >>> lst ['Give me a hug'] >>> lst = testParser('http://facweb.cdm.depaul.edu/asettle/csc243/web/fEThree.html') >>> lst [] >>> lst = testParser('http://facweb.cdm.depaul.edu/asettle/csc243/web/fEFour.html') >>> lst ['JoJo the cat', 'Cuddles are nice', 'Always ready to learn Python'] >>>
Nov 24, 2021
SOLUTION.PDF

Get Answer To This Question

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here