ICS 31 • DAVID G. KAY • UC IRVINE •WINTER 2013
Lab Assignment 3
This assignment is due at the end of lab on Friday, January 25. Material from this lab may appear on the midterm (Tuesday, January 29).
Preparation (Do this part individually, before coming to lab)
(1) If you're just getting enrolled in the class, do everything on the course refrence sheet (the syllabus) under the heading "What to do this week to get started in ICS 31." This includes registering yourself at checkmate.ics.uci.edu and piazza.com, filling out the questionnaire at eee.uci.edu/survey/ics31.w13.q, and turning in your photo to your TA.
(2) Re-read setions 3.3 and 3.5 and read sections 3.1 and 3.2 of the Perkovic text, trying the practice problems (before looking at the solutions). We have already worked with assignment statements and distinguished some data structures as immutable while others are mutable. Section 3.4 explores these issues further, but we recommend skipping that section until after the midterm.
In section 3.2, look at the flowchart diagrams. They're a good way to visualize the semantics (meaning, behavior) of the control structures.
(3) Become comfortable with the terminology of functions: function definitions, function calling, arguments (the values you call the functions with), parameters (the names of those values inside the function, defined in the function header/signature/def line), what it means when we say a function "takes a number and a string", what it means for a function to return a value, the difference between defining a function and calling it.
(4) Read through the Lab Work part of this assignment before you come to lab on Monday. This will give you an idea of what you'll be doing with your partner, but it also contains a variety of explanations of important course material, things you'll need for the assignment, quizzes, and exams. We won't bother repeating this instruction in next week's lab (or thereafter), but of course you should continue to follow it.
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.
(b)
For this assignment, you will create a Python file called lab3.py. Type your answers to all the parts of this assignment into this file; non-Python text can be in comments or multi-line (triple-quoted) strings.
On the first line of the file type a comment with the names and IDs of both partners and some other identifying information, like this:
# Paula Programmer 11223344 and Andrew Anteater 44332211. ICS 31 Lab sec 7. Lab asst 3.
The Python code in your file should produce the specified results when you run the file. When you've finished the assignment, you'll submit this file via Checkmate. (It's a good idea if each partner keeps a copy of the lab work at the end of each session, just in case someone can't make it to the next lab.)
It is also helpful in the grading if you separate your code for each part of the assignment in your lab3.py file. Indicate each part of the assignment in the file with comments like this:
#
#
# Part (c)
#
#
and also include print statements so the different parts are distinguished in the output, for example:
print() # Leaves a blank line. print('\n') does the same thing.
print()
print('---------- Part (c) ----------')
print()
We won't bother repeating these instructions in later lab assignments, but unless we specify otherwise you should still prepare your lab work this way.
(c) At the end of Chapter 3, do exercises 3.36 and 3.43. For each function, put in your lab3.py file a few print statements that call the function with enough different values to demonstrate that it works correctly. Until we get to assert statements, do this for every function you write for a lab assignment.
Do a simplified version of exercise 3.35 that computes and returns (not prints) only the distance between the two points.
Do exercise 3.44.
(d) Exercise 3.32 can be done without an if statement (which we haven't covered yet) by using max and min. Try to solve it that way, but don't spend more than 10 minutes on it until you've finished the rest of the assignment.
Any programming task can be divided into three parts: the requirements (deciding what your program needs to do—for most class assignments, we provide this for you), the design (deciding how to model the requirements, choosing which data structures and which algorithms you'll need), and the implementation or coding (deciding how to say it in Python or whatever programming language you're using). (A fourth part is testing, but as we'll see soon, we start setting up our testing during the design and implementation steps.)
Most of our problems so far have focused on the implementation phase; either we told you the design explicitly or the design was easy to figure out (everybody understands how to double the price of a dish at a restaurant, even if they may not know how to implement that in Python code). That makes sense at the beginning of an introductory course. But Exercise 3.32 requires a little more thinking about the algorithm for solving it using max and min.
There's no automatic process for designing algorithms; most of our problems won't require heavy-duty algorithm design, but every once in a while it's something to think about. One method that may help in this case is to come up with a list of input pairs (hourly wage and number of hours), some of which involve overtime and some of which don't, and calculate by hand the correct results for each pair. Then start with the expression wage * hours, calculate the results of that expression on each of your input pairs, and make adjustments to the expression until it produces the correct results on each of your inputs. (Using a spreadsheet may help automate some of these calculations.)
But don't spend more than 10 minutes on this until the rest of the assignment is done.
(One other note is appropriate to reiterate here: The solution is pretty short; of course you could just get it from a classmate who has solved it already. But even aside from the academic dishonesty, it robs you of the learning you would get from working it out with your partner. The goal isn't the answer; the goal is your learning how to develop and think about algorithms. Just getting the solution would be like getting someone else to do your workouts for you: totally pointless.)
(e) When we sort a list of items, we need a basis on which to compare the items to see whether one is bigger than another. If it's a list of numbers, Python just compares the numeric values; if it's a list of strings, Python compares the strings alphabetically. But what if we're sorting a list of restaurants? As we saw earlier, the sort() method uses the first field of a Restaurant object (in our case, its name) for comparison. We call the basis of comparison the sort key. Wouldn't it be convenient if we could sort lists of complex objects based on some other sort key?
(e.1) Define a function called restaurant_price that takes one argument, a Restaurant, and returns the value of the price field of that Restaurant. This is quite short and easy. But whenever a lab problem asks you to define a function, you also need to include in your file some calls to that function that test it, that demonstrate that the function works correctly. So define a Restaurant or two and print out the results of calling restaurant_price on those functions. (Shortly we'll see assert statements, which are a way of automating this testing process.)
(e.2) Write a sequence of statements that prints out the list of Restaurants RC in order from least expensive to most expensive (best dish). [Hint: As an argument to the sort() method, say key = restaurant_price. Take a second to read this again, paying attention to the terminology so you know what this is telling you to write in Python. Interpreting technical terminology is an important skill; it may also help you to look at the entry for sort() in help(list). Giving key = restaurant_price as an argument to sort() tells sort() how to get the value from each Restaurant that it will compare: By default (without our saying anything), it used the first field, the name of the Restaurant; the key= argument lets us specify a function that takes a Restaurant as input and returns a value—in our example, its price field—to use instead of the name when comparing Restaurants during the sorting process. What's tricky is that we supply the name of a function after key=, but as we'll see later, functions can be useful as components of other computations.]
(e.3) Write a function called costliest that takes a list of Restaurants as its argument and returns the name of the highest-priced restaurant on that list. [You need to pay close attention to the wording of technical specifications like this. This function returns a string, the name of the costliest restaurant; it doesn not return the whole Restaurant object.]
To test this function, create a short list of Restaurants and print the value of calling costliest with that list as its argument.
(f) Write a series of turtle graphics statements to draw a face, with a mouth, a nose, and two eyes. Use your eye-drawing code from part (e). But don't just copy those lines twice! Even if you use copy and paste to avoid tedious retyping, duplicate code is always a problem: It makes the program longer, and if you have to change it, you have to change every copy. If you skip changing one copy of the duplicate code, your program becomes an inconsistent mess. Happily, we've learned how to avoid writing duplicate code in this situation: We design a function called draw_eye to contain our eye-drawing code; then we call that function twice, once for each eye. But there's one more step, because we don't want to draw both eyes in the same place. Our draw_eye function needs a parameter that specifies the starting point for the drawing; then we can call it twice, one with a starting point offset from the other.
Write a function called draw_face that calls functions (that you also write) called draw_eye, draw_nose, and draw_mouth. Your nose and mouth don't have to be as fancy as your eyes; in fact, make them as crude and simple as you can to start with, and only refine them if you have time. Include at least two calls to draw_face in your lab3.py file.
(If you're feeling ambitious and have the time, parameterize other aspects of your feature-drawing functions so you can easily draw faces with different-color eyes, different-sized noses, and so on.)
(g) 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. 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 lab3.py file containing your solutions to parts (c) through (g). It would be an excellent idea to go back and re-read those parts carefully now, to make sure you've completed all the steps specified. It would also be an excellent idea to run your file one last time to make sure all the correct results appear, with no error messages. (If you run into problems, it's probably because you have more than one function with the same name. Change one of the names [everywhere necessary] and try to Run again.)
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. Modified by David G. Kay, Winter 2013.