COS 100: Introduction to Programming

Interim 2021

Lab 12: Lists of lists

Lab 12A: ASCII art


Lab 12B: File processing

The goal of this lab is to practice with reading files and continue to work with 2D lists. This will help you with a later homework project, so you should make sure to save your code. The format is a little different. You are given a long list (!) of tasks. Some of them are not coding exercises but more like worksheet exercises where you are trying to learn some concept. Please ask questions if you have any!
  1. Consider counter2.py, which a slight modification of counter.py from the first project. You should now understand almost all the lines. Deduce the purpose and meaning of these new lines in counter2.py:
    opened_file = open(file_name)
    opened_file.close()
    
  2. Save a copy of the file table.txt. Put it in the same working directory.
  3. Create a program that reads the downloaded file and prints it out. (This should be substantially similar to and, in fact, simpler than counter2.py.) Make sure you close() the file.
  4. Modify the program so there is a function called load_file that takes a file name as input and returns a list, consisting of the lines of the file.

    For example:

    data = load_file("table.txt")
    print(len(data))
    print(data)
    
    should print
    3
    ['1,2,3,4,5\n', '2,7,1,8,2\n', '3,1,4,1,5\n']
    
    Where should you close() the file?

    Important: Your load_file function should work for any file, not just ones with 3 lines. If the file has more lines, a longer list should be returned.

  5. The \n that appears in the output above is a single character that marks the end of a line. Run the following code, one line at a time, in the Shell to understand \n fully:
    s = "ab\ncd"
    s[1]
    s[2]
    s[3]
    len(s)
    s
    print(s)
    
    What is the difference between s and print(s)?
  6. Modify load_file slightly so the new line markers \n are chopped off and not returned:
    ['1,2,3,4,5', '2,7,1,8,2', '3,1,4,1,5']
    
  7. Run the following code, one line at a time, in the Shell to understand how to use split on a string.
    state = "Mississippi"
    state.split("ss")
    state
    state.split("i")
    len(state.split("i"))
    "apple".split("p")
    
    What do you think I was trying to get you to understand by the third line (state by itself)?
  8. Your load_file currently returns a list of strings. Change it so each string is further split into a list of integers. So the return value is a list of lists of integers.
    data = load_file("table.txt")
    print(len(data))
    print(data)
    print(data[1])
    print(len(data[1]))
    print(data[1][3])
    
    should print
    3
    [[1, 2, 3, 4, 5], [2, 7, 1, 8, 2], [3, 1, 4, 1, 5]]
    [2, 7, 1, 8, 2]
    5
    8
    
    Make sure you fully undrestand where each line of output is coming from before proceeding. If your output has a bunch of quotation marks, it means you haven't converted the numbers from strings to integers.

    Important: Your load_file function should work with any file with the format of integers separated by commas, not just ones with 3 lines of 5 numbers each.

  9. Note that the return value of load_file is a list of 3 lists, each a list of 5 numbers. We call each of the 3 lists a row. Recall that rows in a list of lists do not have to be of the same length:
    [[1, 2, 3, 4, 5], [2], [3, 1, 4], [5]]
    
    is a list with four rows, which have lengths 5, 1, 3, and 1, respectively. We call such a 2D list a ragged array to emphasize that it is not shaped like a rectangle.

    In the next lab, we are going to work with lists of lists that do have rows of the same length. We call such a 2D list a matrix to emphasize that it is shaped like a rectangle.


Lab 12C: Matrix functions

In this lab, we will write several functions that take a matrix (2D list of rectangular shape) as input.
  1. I will continue to use the return value of load_file as example. If you couldn't get load_file to work properly, you can work on this lab by manually setting:
    data = [[1, 2, 3, 4, 5], [2, 7, 1, 8, 2], [3, 1, 4, 1, 5]]
    
    Important: Make sure your code below works for any matrix of numbers, not just ones with 3 rows and 5 columns.
  2. Write a function table_print that takes a matrix (like the return value of load_file) and prints it in a table, like so:
    table_print(data)
    
    1 2 3 4 5
    2 7 1 8 2
    3 1 4 1 5
    
  3. Write a function row_sums that takes a matrix and returns a list of the sums of each row:
    print(row_sums(data))
    
    [15, 20, 14]
    
  4. Write a function column_sums that takes a matrix and returns a list of the sums of each column:
    print(column_sums(data))
    
    [6, 10, 8, 13, 12]
    
    Note: This is significantly harder than row_sums.
  5. (Bonus) Write a function transpose that takes a matrix and returns a new matrix where the rows and columns are swapped.
    swapped = transpose(data)
    table_print(swapped)
    
    1 2 3
    2 7 1
    3 1 4
    4 8 1
    5 2 5
    
  6. (Bonus) Write a function table_print_border that enhances table_print by printing borders, like so:
    +---+---+---+---+---+
    | 1 | 2 | 3 | 4 | 5 |
    +---+---+---+---+---+
    | 2 | 7 | 1 | 8 | 2 |
    +---+---+---+---+---+
    | 3 | 1 | 4 | 1 | 5 |
    +---+---+---+---+---+
    
    Can you get the output to line up nicely even when the numbers have different number of digits?