Lab 11: Binary Search and 2D Lists
Goals
After the lab, you should be proficient at
- Adding exception handling
- adapting "basic" binary search for use in another algorithm
- creating and processing 2D lists
Review
Review the slides for today.
Objective: Set up
- Run labhelp
- Copy
the entire
directory
/csci/courses/cs111/handouts/lab11
into yourcs111
directory. - Copy
the Python files (although not the entire directory) from
your
lab10
directory into thelab11
directory so that you can extend your InstaFace application in this lab. - If you haven't completed the Lab 10 social network program and you
don't expect to finish it, you can use my solution, which is in the
lab10_solution
subdirectory of thelab11
directory you copied. You should copy those files into yourlab11
directory. You can also compare your solution to mine.
Objective: How Much Code Have I Written? (6 pts)
You've been writing code for 11 weeks (or so), and the programs have gotten larger. Last week's lab was the largest yet. In the grand scheme of programming, this code is still relatively small, but it's not small to you!
- Make sure that you have all of the code for your assignments.
- From your
lab11
directory in the terminal, execute the command:wc ../lab10/*.py
wc
stands for "Word Count". We called the "word count" command on all the *.py files (i.e., the Python scripts, not other files or directories) in yourlab10
directory. The first column of output is the number of lines, the second is the number of words, and the third is the number of characters in each file. The total for all the files is listed in the last line of output.For example:
170 588 5087 ../lab10/instaface.py 112 284 2747 ../lab10/person.py 282 799 8534 ../lab10/social.py 17 62 574 ../lab10/test.py 581 1733 16942 total
- Run the
wc
command so that you only see the number of lines, using the command-line argument "-l
", i.e.,
wc -l ../lab10/*.py - Finally, write the output of the command into a file, using
the
>
operator, i.e.,
wc -l ../lab10/*.py > mywc10.txt - View the output of the command that was saved in
the
mywc10.txt
file, using the Unix commandsmore
, e.g., more mywc10.txt, orcat
, e.g., cat mywc10.txt or opening the file in a text editor. - Next, look at all the code you've written throughout the semester.
Run the command wc -l ../*/*.py.
This is an
overestimate because it likely contains code you didn't write
(e.g.,
graphics.py
andtest.py
) plus it includes comments, but it gives you some idea of what you've done throughout the semester. - Then save the results of that command to a file: wc -l ../*/*.py > mywc.txt
- In comments near the top of
instaface.py
, reflect on the amount of code you wrote for the last lab and for the semester.
Note that the number of lines does not distinguish between lines of codes and lines of comments, so this is an overestimate of how much code you wrote.
Objective: Programming in Python
Adding Exception Handling to File-Reading Methods (10)
- Update your
SocialNetwork
class's file-reading methods so that they do exception handling. The methods should perform exception handling of IOErrors and return True iff the file was successfully read. If there was an exception, then print a descriptive error message and return False. We do this for better error handling, since we are creating larger applications, and bad input/errors can cause big problems. - As always, test your new implementations! (How do you do that programmatically?)
- Update the doc strings on the methods to reflect this change in the method's interface.
- Finally, update your InstaFace interface to print a helpful message (e.g., "You have successfully read in data/large.txt") when the file-reading methods return True. You don't need to do anything in the false case because that should be handled in the methods.
Development reflection: It's important that adding exception handling is done last, as in, after you made sure the rest of your code worked. Otherwise, exception handling can hide bugs in your program.
No output yet. Wait until after you complete the next parts and the output for this part will be included with the rest.
Adding Search Functionality to InstaFace (44 pts)
As discussed in class, you will update your InstaFace to find a
person with a certain name. For improved usability (i.e., for the
user to get the results they expect), it shouldn't matter if the user
capitalizes the name appropriately. We also need to make a few
changes to the original binary search function so that it can
be turned into a method of the SocialNetwork
class.
For each of the classes, you should save an output file with the tests you ran.
Add __lt__(self, other)
method
to Person
class (12)
If we implement/override the __lt__
method, we can compare
two Person
objects using <
. (What
does __lt__
stand for?) If __lt__
is
implemented, then list
's sort
method will
use __lt__
to order the Person
objects, by
default. By implementing __lt__
, we don't need to use
the key
parameter when calling the sort
method.
def __lt__(self, other): """ Takes as a parameter a Person object named other. Returns True if this person's name, lowercased, comes before the other person's name, lowercased, alphabetically. Otherwise, returns False. """
- Implement the above method in
the
Person
class. - Test the method by comparing two
Person
objects, for example (as we did in the Card class):print(person1 < person2) print(person2 < person1) test.testEqual(person1 < person2, True) test.testEqual(person2 < person1, False)
The above print statements should print either
True
orFalse
. - Then, create a list of
Person
objects and make sure that sorting the list of Person objects does what is expected. (What is expected?)
Searching for a Person with the given name (22)
Add a search method to
the SocialNetwork
class. The method will take as
a parameter the name to search for and returns a person who
has that name.
def searchForPerson(self, name): """ Search for the person with the given name (a string) in the social network. Returns a Person with this name, ignoring case, or None if no person with this name (ignoring case) exists in the social network. """
Note, unlike the function we wrote in class, the method
does not take as a parameter the list of Person
objects. Where should that list of Person objects come from?
Your method should leverage binary search to find a person that has the given name. Recall: What does binary search require of the list it searches?
For better usability, the search shouldn't care whether the name is
capitalized correctly. Therefore, you should lowercase the given
name to search for to get the most intuitive results. (Save the
result in a variable so you don't have to keep performing these
operations on the name.)
If the given key is lowercased, what should you do to
the Person
's name?
If there is a for
loop in
your method, you're likely essentially implementing linear search and not
getting any benefit from binary search.
What are good test cases for this method? Start by searching for a
name in a small number of users. Note that we now have two different
ways to search the social network--by name or by id. You can use each
to check the other, i.e., you can check the Person you found by id is
the same as the Person you found when you look them up by name. After
(in addition) to testing small networks, you should test
using data/large.txt
, which has a bunch of users in it, or some
other similarly large set of people (perhaps that you created).
The user interface will be responsible for printing out the person with that name or printing out a message if no one matches.
We've been programming for 11 weeks now. Do what you can to help you visualize what is happening--draw pictures, print out variables. Use small datasets instead of trying to work on a large set. Name variables by their data types so you remember what you're working with. Review/execute related examples to make sure you understand what they did.
Adding an Option to your InstaFace User Interface Program (10 pts)
Add an option that allows the user to search for a person with a given name.
Example Run:
ID Name Num Friends --------------------------------------------- astley Rick Astley 1 doej Jane Doe 2 ht8 Henry VIII 2 schmoj Joe Schmo 1 Select one of the following options: (D)isplay the social network (V)iew a person in the social network (S)earch for people in the social network Add (P)eople to the social network from a file Add (C)onnections to the social network from a file Add a (U)ser to the social network Add a pair of (F)riends to the social network E(X)port the social network (Q)uit the program Which option do you want? s What is the name of the person you want to find? jane doe Jane Doe (id: doej) has 2 friends Which option do you want? s What is the name of the person you want to find? Jane No person named Jane found.
Demonstrate InstaFace
Demonstrate that your program works in IDLE (only the new functionality: searching and exception handling) and save the output in an appropriately named ".out" file.
You must demonstrate the search functionality on a larger data set. How can you add more people to your social network easily?
Working with 2D Lists (40)
For each of the following problems, create a new Python script, named using our usual naming.
After you've developed a correct solution to each program, restart IDLE or close and reopen the IDLE "shell" by running the program again (using F5), demonstrate that the program works using several good test cases, and save the output to a file named lab11.x.out, where x is the problem number.
- (10 pts) Create a 2D list that looks like:
[ [0,1,2], [1,3,5], [2,5,8], [3,7,11] ]
To make each row, you can either use the
range
function and/orappend
to a list, but do not create the list by typingtwod=[ [0,1,2], [1,3,5], [2,5,8], ... ]
Print out the list--as a list--after each time you add a row. Do not worry about formatting yet. (See the next problem.)
- (15 pts) Copy the previous program for this program. Add a
function called
prettyPrint2DList
that takes a two-dimensional list of integers as a parameter and prints that list so that it looks like the below format, where each number should be right-justified within 5 spaces. (You can assume that the integers in the list are at most four digits.)Test on the list you created in the last program, as well as several different 2-d lists, all in one execution of the program. What would make good tests? (Note that you can't programmatically test display functions.)
Example lists displayed:
0 1 2 1 3 5 2 5 8 3 7 11
10 11 12 13 100 3 5 8 2 1150 8 9999 3 7 1111 399 4 5 6 7
- (15 pts)
- Open up
connectfour.py
that you copied earlier and look at theConnectFour
class.Familiarize yourself with its attributes and how other methods are implemented. Investing your time in understanding the existing code will result in faster implementation of the solution. What is the data for this class? How do the (fully implemented) methods manipulate this data?
- Uncomment the
makeMove
method and its docstring comment and implement the method. Make sure the indentation is correct. Adhere to the method's comment description when implementing the method. - Uncomment the code in the
play
method, as described in the code. Runconnectfour.py
to test your game.
You should only have to modify
connectfour.py
--notcsplot.py
. - Open up
You won't submit any output from this program.
Extra Credit: Searching (up to 8 points)
The search functionality is pretty limited -- it only finds one person with the matching name.
Modify the binary search to find all the people with a
certain name. If you search for "Jane Smith", there is probably
more than one person with that name. Modify your search so that
it returns a list
of Person
objects,
rather than just one of the possible people. Where will the other
people with that same name be with respect to the person you found
using binary search? What should your method return if there is
no Person
with that name? To test this method, you
will need to update the data files or somehow include multiple
people with the same name.
You should demo this functionality. Update any dependent code to make sure that making this change doesn't break it.
Extra Credit: ConnectFour
Implement the _isDraw
(up to 4 pts)
or_isWon
methods (up to 10 pts) of the ConnectFour class. You can receive partial
credit.
Alternatively, you can improve the _computerChooseColumn
method that chooses the "best" column to place the checker (up to 8
pts). A naive first approach (which is currently implemented) is to
randomly pick a column. A more sophisticated approach is to assign a
score to each column that says how "good" a column is for you and
select the column with the highest score. What properties would make
the column's score increase?
Finishing up: What to turn in for this lab
- Move
csplot.py
into the parent directory. (This is a large file that you don't want to print out.)
-
- Create the printable lab assignment, using the
createPrintableLab
command. - View your file using the
evince
command. - Check that the PDF contains all (and only) the necessary files.
- Print the file from evince. You can print to other printers if there are issues with the computer science printers (which do not cost you anything to print computer science work).
- Submit
your lab directory into your
turnin
directory. - Log out of your machine when you are done.
Note that each command links to a page with more information about using the command.
Labs are due before the beginning of Friday's class.
Ask well before the deadline if you need help turning in your assignment!
Grading (100 pts)
- Python programs: 94 pts; see above for breakdown
- UNIX practice: 6 pts (
mywc.txt
file submitted, comments ininstaface.py
)