Homework 1 Discussion and Problem Solving

Livecode link Livecode tests

Homework 1 Discussion

We’ll start by looking at some partial solution code for homework 1. While I won’t put it in the notes, I have no problems with showing some functions and discussing them in class. But there’s something very important we need to agree to: this code is a solution, not the solution. There’s lots of ways to do this assignment, and nothing I’m about to show you is perfect.

(See lecture capture for specifics.)

Problem Solving

Let’s say we have a problem we need to solve, and we want to solve it by writing a program. How should we start?

In an earlier lecture, I recommended writing down what data you have (and what form it’s in), and what you want to produce. From there, you can break down the problem into smaller pieces. If you can solve each subproblem, and then combine them together, you can solve the whole problem.

Some subproblems can be solved by writing helper functions, and we’ve seen a number of examples of this. Other times, subproblems correspond to calls to built-in functions, or particular variables we keep track of. Breaking down problems is a skill you develop over time, and it’s a skill we’ll be practicing a lot in this class.

The most important thing to remember is: even if you aren’t sure how to do something in Python, you can still make progress. Here’s an example.

Example 1: Cast of Characters

Given a string that contains the text of a book, suppose we want to find all the words that begin with a capital letter, then make each word all caps, and then return them all in a set. We can call our function cast_of_chars, short for “cast of characters”. This isn’t quite the right name for what we’ll get; we’ll see lots of words at the beginning of sentences, too.

Now that we know the type of our function’s input and output, let’s go ahead and write some examples, in test form:

# in lecture06.py:
def cast_of_chars(txt: str) -> set:
  pass
# in test_lecture06.py:
def test_cast_of_chars():
  assert cast_of_chars("") == set()
  assert cast_of_chars("Tim") == {"TIM"}
  assert cast_of_chars("'hello,' said TIM") == {"TIM"}
  assert cast_of_chars("hello Tim hello Tim hello Annabelle") == {"TIM", "ANNABELLE"}
  # This example points out something we might need to _decide on_. Why?
  assert cast_of_chars("hello Tim hello TiM hello Annabelle") == {"TIM", "ANNABELLE"}

Ok, now we have a (very) rough understanding of what the function should do. How do we get started? Well, let’s keep following the recipe.

Now, let’s break down the task into a bunch of little pieces. What might we need to do?

Think, then click!

In class, some thoughts included:

  • splitting the input into a list of separate words;
  • removing punctuation from the words (not something I started with, but someone asked!);
  • filtering out uncapitalized words; and
  • fully capitalizing each word remaining.


Note that these suggest a bit of structure: one naturally flows into another, and so on. This won’t always be the case, but it certainly helps here! We can write a skeleton for the function. Maybe we don’t yet know how to actually do all the subtasks, but we can give the result of each a name and record which uses which.

Think, then click!
# in wordcount_test.py:
def cast_of_chars(s: str):      
    words = [] # ??? should use s
    caps_words = set() # ??? should use words
    cleaned = set() # ??? should use caps_words
    all_caps = set() # ??? should use cleaned
    return all_caps


Do we know how to split a string up by blank space? Yes: use split()! Also, do we have an idea how we might pass over a list, looking for capitalized words? Yes: use a loop! Even if we don’t know what to do in that loop, or how exactly to detect capitalization, we can fill it in. And so on. (Remember to look for the # ??? comments I’ve left to remind myself to fill in a hole later.)

Let’s run another exercise where you help me figure out where different potential Python lines go. We’ll proceed in a couple stages, however. Starting from the last partial program, let’s add some of that structure. These lines aren’t the only lines we’ll need, so just focus on putting them into the stencil roughly where they need to go, and perhaps add some # ??? comments around where you think there are still holes in the program.

caps_words.add(word)
cleaned.add(word) 
for word in cleaned:
words = s.split() 
for word in caps_words: 
for word in words:         
all_caps.add(word) 

We should end up somewhere like this:

Think, then click!
# in wordcount_test.py:
def cast_of_chars(s: str):      
    words = s.split() # split by blank space
    caps_words = set()
    for word in words:         
        caps_words.add(word)  # ??? add only if capitalized
    cleaned = set()
    for word in caps_words: 
        cleaned.add(word) # ??? add version without punctuation             
    all_caps = set()
    for word in cleaned:
        all_caps.add(word) # ??? add capitalized version
    return all_caps


Notice that the shape of the function is beginning to appear, even if we aren’t sure how to do the smaller pieces yet. Instead of trying to write the entire function at once, I’ve got incomplete functionality, like just adding a word instead of cleaning it or capitalizing it first. Gradually, we can fill these in, too.

Think, then click!
# in wordcount_test.py:
def cast_of_chars(s: str):      
    words = s.split() # split by blank space
    caps_words = set() 
    for word in words: 
        if word[0].isupper(): # check first letter
            caps_words.add(word)
    cleaned = set()
    for word in caps_words: 
        cleaned.add(word.replace(",", "")) # remove commas
    all_caps = set()
    for word in cleaned:
        all_caps.add(word.upper()) # fully uppercase
    return all_caps


Breaking problems down like this is useful, even if you have decades of programming experience. If you watch an long-time expert programmer working, it might appear like they aren’t following this process, but they’ve likely internalized it so well that it’s hard to see. If you’re just starting to learn to play piano, would you judge your progress against someone with decades of full-time experience? I hope not!