ICS 31 • DAVID G. KAY • UC IRVINE • WINTER 2013
Lab Assignment 4
This assignment is due at the end of lab on Friday, February 1.
Preparation (Do this part individually, but do whatever preparation you need for the midterm first; the early parts of this assignment may help you review on Monday in lab)
(1) After you get your midterm back from your TA, review what you missed, and learn the concepts you didn't know before. Then take the midterm again for yourself: Cover up your answers and re-create them from scratch. (It's okay to skip the questions you answered correctly the first time, but it wouldn't hurt to do them again, either.) The topics on the midterm are fundamental; you'll have a hard time moving forward without mastering them.
(2) Read any sections of Chapter 3 that you haven't read yet, particularly sections 3.4 and 3.6. Try the practice problems, especially 3.12 and 3.13 (before looking at the solutions). At www.pythontutor.com you can run simple Python code and see the values change in memory; it may be helpful for probems 3.12 and 3.13.
(3) Do at least four of the parts of Exercise 3.21. Go back and look at section 2.4 to remind yourself how the range function works. This is a key programming skill, to be able to read a description of a language feature and then use it correctly.
Lab Work (Do this part with your partner in lab)
(a) Choose a partner for this assignment and make sure the TA knows who your partner is. Remember that you'll choose a different partner for each lab assignment, so you'll work with this partner only this week. Make sure you know your partner's name (first and last) and contact information (Email or cellphone or whatever) in case one of you can't make it to lab.
Note that doing these problems by yourself, at home, is not pair programming and will not receive full credit (at least for participation). It's great if you want to work outside of lab, but whatever you prepare alone you must explain to your partner so that he or she understands it as well as you do. (This is to your benefit as well as your partner's: One of the most common workplace situations (and not just in science and technology) is to bring a co-worker up to speed on some project.)
Scary warning: There's another reason to do all your work jointly with your assigned partner: You protect yourself from getting in trouble for academic dishonesty. Something like this occasionally happens in programming classes: Partner A works alone and submits some code that Partner B didn't work on and hasn't examined. But Partner A gets that code from another student in the class, or a roommate who's a CS major, or someone who took the course before. All of these are instances of academic dishonesty, and often they come to the notice of the TAs or instructor. Then both partners, A and B, get in trouble because the work is submitted jointly by both students. These are difficult and unhappy situations; you can avoid them by doing pair programming properly and, when you get stuck, asking the lab tutors, the TAs, the instructor, or Piazza for help.
(b)
Prepare your lab4.py file as in previous labs, including a line like this:
# Paula Programmer 11223344 and Andrew Anteater 44332211. ICS 31 Lab sec 7. Lab asst 4.
All the Python code you write for this assignment should be executable (i.e., not commented out) in your lab4.py file and should produce the correct results when you (and the TA) run the file. We can't give you credit for code that doesn't run and produce the correct results. Unlike on exams, on lab assignments there's rarely partial credit for partially working code because you have the ability to test it out and refine it until it does work correctly.
As you work, organize and prepare this file according to part (b) of Lab 3.
(c) Do exercises 3.17, 3.18, 3.19, and 3.20.
(d.1) Write a function called is_vowel that takes a
one-character-long string and returns True if that character is a vowel and False otherwise. [A vowel, for our purposes here, is one of the letters a, e, i, o, or u (lower case or upper case).] Page 67 of the textbook shows how to compute this; your task here is to package this up into a function that returns a boolean value. [Please check that the function name is capitalized precisely as shown above; it helps your TA in the grading.]
Your function definition should follow the "design recipe" pattern we described in class:
def double (n: int) -> int:)" Return twice the value of the parameter "). Regular quotation marks are fine for one-line comments; you need triple-quotes if your docstring extends over two or more lines.print(double(7), "should be 14") and print(double(0), "should be 0")), but in the long run it's better to use assert statements (e.g., assert(double(7) == 14) and assert(double(0) == 0)).You should do all of this before you write the code for the body of the function (which follows the pattern on page 67 of the text). And we expect you to do this for every function you write from now on. If you ask a TA or tutor for help and you haven't done it, they'll just send you back to do it. (Of course, if you have questions about how to do this, they'll be glad to help.)
[Novice programmers are often tempted to code the body of this task as
if ... :
return True
else:
return False
But this is rather clumsy and redundant, because the boolean expression itself (the "..." above)
has exactly the value you want to return; you should just say return ... and be done.
Take a minute to re-read this and understand it fully. ]
Finally, run your code (including the tests) to make sure the tests all pass. This is the pattern you will follow for every function you design and code.
(d.2) Write a function called print_nonvowels that takes a string and prints out all the characters in the string that are not vowels. Use your is_vowel function (and one of the logical/boolean operators). (Note that this function prints its result rather than returning it. Whenever you define a function, the first thing to determine is whether the result should be returned or printed. When in doubt, return the value and let the program that called the function decide what to do with it. For class purposes, we'll typically just tell you which to do, as we did here.) This task is related but not identical to the tasks described on page 67.
Write some tests, enough so that if they pass, you're convinced that your function works correctly. And run the tests, of course.
(d.3) Write a function called nonvowels that takes a string and returns a string containing all the characters in the parameter string that are not vowels. Since you're returning a string instead of printing a character at a time, you'll need to construct that string in your function. Start with a variable (let's call it result) whose value is the empty string. Each time you find a nonvowel, add it to the end of result. Then, once you've gone through the whole parameter, result is what you return. [We just gave you the algorithm; your job is to implement it in Python.]
Functions that return values are somewhat more convenient to test than functions that print values. You could do it the same way, printing out the tests and the results or printing out boolean expresions that are true if the test passes. Instead of print statements, though, you can use assert statements as shown below. Their advantage is that if the test passes, nothing happens, so you can leave the assert statements in your code after you're satisfied your function works, without their cluttering up your output. (It's good to keep the assert statements there because later you may make changes that "break" your existing code, or you may need to change your existing code, and with the tests still in place you'll find any problems at the earliest possible time.)
Here are some assert statements for double and for is_vowel; note that the argument to assert is a boolean expression.
assert(double(0) == 0)
assert(double(17.5) == 35)
assert(double(-223344) == -446688)
assert(is_vowel('a'))
assert(is_vowel('U'))
assert(not is_vowel('X'))
assert(not is_vowel('?'))
To see what happens when a test fails, assert something false like assert(double(2)==5). (Note that when an assertion fails, there could be two reasons: (i) Your function may be incorrect, or (ii) your assertion—what you think the right answer is—may be wrong. You should consider both possibilities).
Write some tests for nonvowels using assert statements.
(d.4) Write a function called consonants that takes a string and returns a string containing all the letters in the parameter string that are not vowels. (This is not the same as nonvowels, whose definition refers to "characters," which include digits and spaces and punctuation. Did you test nonvowels with strings including non-letters? If not, go back and do it, changing the function's definition if necessary to make it work correctly.)
Before you write the body of the function, follow the "design recipe" steps: specify the types of the parameter and return value; include a short purpose statement as a docstring; write examples in the form of assert statements.
(d.5) Write a function called select_letters that takes two parameters, both strings, and returns a string. If the first parameter is 'v', it returns a string containing all the vowels in the second parameter; if the first parameter is 'c', it returns a string containing all the consonants in the second parameter. If the first parameter is anything else, it returns the empty string. So, select_letters('v', 'facetiously') would return aeiou and select_letters('c', 'facetiously') would return fctsly. [If you count Y as a vowel, your results will be slightly different.]
(d.6) Write a function called hide_vowels that takes a string and returns a string in which every vowel in the parameter is replaced with a hyphen ("-") and all other characters remain unchanged. After your testing shows that it's correct, try running it with a couple of sentences; you may be able to understand the sentences even with all the vowels hidden.
(e) Do two of Exercises 3.22, 3.23, and 3.24.
(f) You can download code from http://www.ics.uci.edu/~kay/python/restaurants.py that defines a list called RL that contains 26 Restaurant objects.
(In that file, each of the 26 restaurants is given an individual variable name, R1 through R26. That is not necessary; we could create the list of restaurants as we did in Lab Assignment 2, by putting 26 calls to Restaurant() within square brackets. But having individual variable names makes constructing tests more convenient; we can say, e.g., assert(cheapest(RL) == R10).)
Paste the code into your lab4.py file.
(f.1) Write a function called alphabetical that takes a list of restaurants and returns that list in alphabetical order by name. Except for making this a function, you did this task in last week's lab.
(f.2) Write a function called alphabetical_names that takes a list of restaurants and returns a list of the names of all the restaurants in alphabetical order by name. [One of the things you learn in this course is to read technical documents very closely. Part (f.1) asked for a list of restaurants; this part asks for a list of strings, with each string the name of a restaurant.]
(f.3) Write a function called all_Thai that takes a list of restaurants and returns a list of all the Thai restaurants (i.e., whose cuisine attribute is Thai). The body of the function follows the same pattern as your vowel-selecting function above. Recognizing these similar patterns is a programming skill you will develop.
(f.4) Write a function called select_cuisine that takes a list of restaurants and a string representing a cuisine. It should return a list of all the restaurants that serve the specified cuisine.
(f.5) Write a function called select_cheaper that takes a list of restaurants and a number (a float) and returns a list of all the restaurants whose price is less than the specified number.
(f.6) Write a function called average_price that takes a list of restaurants and returns the average price of (the best dishes at) those restaurants. (You may wish to write a separate function that takes a list of restaurants and returns the sum of the prices of (the best dishes at) those restaurants. But that's not required.)
(f.7) Write a print statement that calls one or more of the functions you defined above to print the average price of the Indian restaurants in the list RL.
(f.8) Write a print statement that calls one or more of the functions you defined above to print the average price at the Chinese and Thai restaurants (taken as one group) in the list RL.
(f.9) Write a print statement that calls one or more of the functions you defined above to print a list of the names of all the restaurants in RL with a price under $15.00.
(g) Do problems 3.25 and 3.26.
(h) Remember that each partner must complete a partner evaluation form and submit it individually. Do this by connecting to eee.uci.edu and choosing the Survey tool for your lab section of ICS 31. Make sure you know your partner's name, first and last, so you can evaluate the right person. Some students have been forgetting to specify their partner's name on the survey; from now on, if you forget your partner's name we won't give you credit for completing the evaluation. Please complete your evaluation by the end of the day on Friday, or Saturday morning at the latest. It only takes a couple of minutes and not doing it hurts your participation score.
What to turn in: Submit via Checkmate your lab4.py file containing your solutions to parts (c) through (g). Remember what we've said in previous labs about rereading the assignment and rerunning your Python files.
Also remember that each student must complete a partner evaluation form by logging in to eee.uci.edu and selecting the Survey tool; these evaluations contribute to your class participation score. Get in the habit of doing this every week on Friday after you've submitted your assignment; the survey closes on Saturday.
Written by David G. Kay in Fall 2012 for ICS 31, based in part on assignments from ICS H21 and Informatics 41. Modified by David G. Kay, Winter 2013.