Lab 11: Binary Search and 2D Lists

Goals

After the lab, you should be proficient at

  1. Adding exception handling
  2. adapting "basic" binary search for use in another algorithm
  3. creating and processing 2D lists

Review

Review the slides for today.

Objective: Set up

  1. Run labhelp
  2. Copy the entire directory /csci/courses/cs111/handouts/lab11 into your cs111 directory.
  3. Copy the Python files (although not the entire directory) from your lab10 directory into the lab11 directory so that you can extend your InstaFace application in this lab.
  4. 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 the lab11 directory you copied. You should copy those files into your lab11 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!

  1. From your lab11 directory in the terminal, execute the command:
    wc ../lab10/*.py

    wc stands for "Word Count". You called the "word count" command on all the *.py files (i.e., the Python scripts, not other files or directories) in your lab10 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    
    
  2. Run the wc command, using the command-line argument -l, so that you only see the number of lines, i.e.,
    wc -l ../lab10/*.py
  3. Note that the number of lines does not distinguish between lines of code and lines of comments, so this is an overestimate of how much code you wrote.

  4. Finally, write the output of the command into a file, using the > operator, i.e.,
    wc -l ../lab10/*.py > mywc10.txt
  5. View the output of the command that was saved in the mywc10.txt file, using the Unix commands more, e.g., more mywc10.txt, or cat, e.g., cat mywc10.txt or opening the file in a text editor.
  6. 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 and test.py) plus it includes comments, but it gives you some idea of what you've done throughout the semester.
  7. Next, we're going to remove some of the files that you didn't write:
    wc -l `ls ../*/*.py | grep -v graphics.py | grep -v csplot.py | grep -v test.py`
  8. Then save the results of that command to a file:
    wc -l `ls ../*/*.py | grep -v graphics.py | grep -v csplot.py | grep -v test.py` > mywc.txt
  9. In comments near the top of instaface.py, reflect on the amount of code you wrote for the last lab and for the semester.

Objective: Improving Our Social Network

Adding Exception Handling to File-Reading Methods (12)

We are creating larger, more complex applications. Our program can't simply crash if there is bad input or errors. This is a job for exception handling!

  1. 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.
  2. Update the methods' doc strings.
  3. As always, test your new implementations! (How do you test these methods programmatically?)
  4. Update the doc strings on the methods to reflect this change in the methods' interfaces.
  5. Finally, update your InstaFace code to print a helpful message (e.g., "You have successfully read in data/large.txt") when the file-reading methods return True (only). You don't need to do anything in the False case because displaying an error message should be handled in the modified SocialNetwork methods.

Development reflection: It's important to implement exception handling 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.

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 to get the "natural" ordering of Person objects.

    def __lt__(self, other):
        """
        Parameter:
            other is a Person object to compare with this Person object
        Returns True if this person's name, lowercased, comes before
        the other person's name, lowercased, alphabetically.
        Otherwise, returns False.
        """
  1. Implement the above method in the Person class.
  2. Test the method by comparing two Person objects, for example (as we did in the most recently modified 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 or False.

    Consider what cases you should test, i.e., what those Person objects in the tests represent. You should also have more tests than just what is above.

  3. Then, create a list of Person objects and test that sorting the list of Person objects does what is expected. (What is expected?)

Searching for a Person with the given name (22)

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
doej: Jane Doe 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.

Demonstrating Classes

For each of the classes, save an appropriately named output file showing all the tests you ran.

Demonstrate InstaFace

Demonstrate that your InstaFace 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 typical naming conventions.

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.

  1. (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/or append to a list, but do not create the list by typing twod=[ [0,1,2], [1,3,5], [2,5,8], ... ]

    Print out the list--as a list--after you add each row. Do not worry about formatting yet. (See the next problem.)

  2. (15 pts) Copy the previous program for this program. Add a function called pretty_print_2Dlist 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 functions that only display something.) You can just hardcode the two-dimensional test lists. The goal now is just testing.

    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
    
  3. (13 pts)
    1. Open up connectfour.py that you copied earlier and read through the ConnectFour 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?

    2. Uncomment the make_move method and its docstring comment and implement the method. Make sure the indentation is correct. Adhere to the method's docstring when implementing the method.
    3. Uncomment the code in the play method, as described in the code. Run connectfour.py to test your game.
    4. You should only modify connectfour.py--not csplot.py.

    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, but often, more than one person has the same name (which is why we need the user ids!).

Create a new method called findAllPeople that takes as a parameter the name you are looking for.

Copy the contents of your searchForPerson method's contents to start this method.

Then, 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.

Demo this functionality. Update any dependent code to make sure that making this change doesn't break it.

Extra Credit: ConnectFour

Implement the _is_draw (up to 3 pts) or _is_won methods (up to 10 pts) of the ConnectFour class. You can receive partial credit for is_won.

Alternatively, you can improve the _computerChooseColumn method that chooses the "best" column to place the checker (up to 7 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 the computer/player 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

  1. Move csplot.py into the parent directory. (This is a large file that you don't want to print out.)
  2. -

    Note that each command links to a page with more information about using the command.

  3. Create the printable lab assignment, using the createPrintableLab command.
  4. View your file using the evince command.
  5. Check that the PDF contains all (and only) the necessary files.
  6. 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).
  7. Submit your lab directory into your turnin directory.
  8. Log out of your machine when you are done.

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)