Session 14

Decomposing Problems and Solutions

CS 1510
Introduction to Computing

Opening Exercise: A Random Walk

Your friendly professor tends to get lost in thought. He also likes to walk randomly while thinking. Suppose he takes one step each second. If each step is equally likely to be north, south, east, or west, how far will end up from home after thirty minutes of deep thought?

Write a Python program that simulates his walk.

Start him at location (0,0) and print his final location.

Random Variations

Yesterday, we used two functions from Python's random module: randint() and random(). They can be useful when implementing games of chance, which require an appearance of randomness, and when implementing programs based on probabilities observed in the world. The random module contains a number of useful functions; we may see a few later.

We also used a new form of the import command. In the past, we have imported an entire module, math, and used names defined in it by 'qualifying' the name with the package name:

    import math
    quadrant = math.pi / 2

We could have done the same with random:

    import random
    die_1 = random.randint(1,6)
    game_result = random.random()

The result can be code that is a little verbose. The from-import command let's us import a single name:

    from random import randint
    die_1 = randint(1,6)

    from random import random
    game_result = random()

And, yes, you can do that with names from the math module, if you'd like!

Opening Solution: A Random Program

Even a small program presents us with challenges. Let's break this task down:

Take a single step.

We have to choose randomly from among four alternatives: north, south, east, or west. We could do this with a four-way choice.
    choice = randint(1,4)
    if choice == 1:      # north
        y += 1
    elif choice == 2:    # south
        y -= 1
    elif choice == 3:    # east
        x += 1
    else:                # west
        x -= 1

This works fine. Unfortunately, the choices don't map onto the real world in any way, which makes them harder to understand and modify. Can we do better?

Let's break this into two decisions: a choice of magnitude, {-1, +1}, and a choice of dimension, {x, y}.

    if random() < 0.5:
        change = 1
        change = -1

    if random() < 0.5:
        x += change
        y += change

This code isn't much longer, but it does have two calls to random(). By separating magnitude and dimension, we have more flexibility when making changes.

Take multiple steps.

This isn't so bad. We make "take one step" the suite of statements for a loop. This loop should execute once for each second in thirty minutes, or 60 * 30 = 1800 times.

Notice that we don't include "define starting location" in the loop's suite of statements. What happens if we do?


All is well. Our program works. It seems I don't wander too far from home very often. Suppose I do this every day for a year. On average, how far do I get from home?

To answer this question, we need to have me take many walks, and then take the average of final locations. This is an application of the good ol' running total pattern:

Our current program takes a single walk. We need to make its body the suite of statements for the loop that computes our running total. This loop should execute however many walks make up our experiment, in this case, 365.

... it looks like, on average, I ended up between 0 and 3 steps away from home in either direction. That's good. It's best not to have absent-minded professors wandering too far from him.

The resulting program is an interesting combination. It comprises two running total loops, one nested inside of the other. We can think of each as a single thing ('take a walk' or 'run an experiment') or in terms of its parts (define summing variable, for loop). Thinking of multiple statements as a single entity can help us write larger programs more efficiently, because it reminds us that some statements have to move together.

Even the most complex program is built up in a similar way from smaller parts that we can understand. As you become comfortable with individual statements, try to think of problems and solutions in terms of the common patterns. This will allow you to think at a higher level as you break problems down and build programs up.


Use the same process when you design programs:

This is how the pros work.

Lessons from the Lab

Lab 7 asked you to build programs similar to our random walk program. In each case, you could build the program in steps.

For Task 1, the progression was identical to the walk:

For the second, the progression was one step farther:

The resulting programs have a similar "shape" as our random walk programs, too.

How can we eliminate all the repetition in our if and if statements? We are poised to learn some new ideas...

Next Idea: Files

A file is...

A file is a string of characters stored outside of our program.

A file is a sequence of lines, where each line is string of characters.

Wrap Up

Eugene Wallingford ..... ..... October 9, 2014